Class: CallMap::CallbackExtractor

Inherits:
Prism::Visitor
  • Object
show all
Defined in:
lib/call_map/callback_extractor.rb

Overview

Extracts before_action callbacks from a class body that apply to a given action.

This is a Prism boundary class — Prism node types are referenced only here.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(action_name) ⇒ CallbackExtractor

Returns a new instance of CallbackExtractor.



99
100
101
102
103
# File 'lib/call_map/callback_extractor.rb', line 99

def initialize(action_name)
  super()
  @action_name = action_name
  @events = []
end

Instance Attribute Details

#eventsObject (readonly)

Returns the value of attribute events.



105
106
107
# File 'lib/call_map/callback_extractor.rb', line 105

def events
  @events
end

Class Method Details

.extract(source, action_name, owner:) ⇒ Array<Hash>

Returns callback events in declaration order: { type: :add, call: MethodCall } for before_action, { type: :skip, name: String } for skip_before_action. Order matters — a callback re-added after a skip runs again.

Parameters:

  • source (String)

    the file source

  • action_name (String)

    the action method name

  • owner (String)

    the class name to scope extraction to

Returns:

  • (Array<Hash>)

    callback events in declaration order: { type: :add, call: MethodCall } for before_action, { type: :skip, name: String } for skip_before_action. Order matters — a callback re-added after a skip runs again.



18
19
20
21
22
23
24
25
26
# File 'lib/call_map/callback_extractor.rb', line 18

def self.extract(source, action_name, owner:)
  root = Prism.parse(source).value
  class_bodies = find_class_bodies(root, owner)
  return [] if class_bodies.empty?

  extractor = new(action_name)
  class_bodies.each { |body| body.accept(extractor) }
  extractor.events
end

Instance Method Details

#visit_call_node(node) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/call_map/callback_extractor.rb', line 107

def visit_call_node(node)
  if node.name == :before_action && callback_applies?(node)
    extract_callback_names(node).each do |name|
      call = MethodCall.new(receiver: nil, method_name: name, line: node.location.start_line,
                            callback: "before_action")
      @events << { type: :add, call: call }
    end
  elsif node.name == :skip_before_action && callback_applies?(node)
    extract_callback_names(node).each { |name| @events << { type: :skip, name: name } }
  end
  super
end

#visit_class_node(_node) ⇒ Object

Callbacks belong to the class they are declared in — do not descend into nested classes/modules or method bodies within the target class body.



122
# File 'lib/call_map/callback_extractor.rb', line 122

def visit_class_node(_node); end

#visit_def_node(_node) ⇒ Object



125
# File 'lib/call_map/callback_extractor.rb', line 125

def visit_def_node(_node); end

#visit_module_node(_node) ⇒ Object



123
# File 'lib/call_map/callback_extractor.rb', line 123

def visit_module_node(_node); end

#visit_singleton_class_node(_node) ⇒ Object



124
# File 'lib/call_map/callback_extractor.rb', line 124

def visit_singleton_class_node(_node); end