Class: Woods::Extractors::CallbackAnalyzer
- Inherits:
-
Object
- Object
- Woods::Extractors::CallbackAnalyzer
- Defined in:
- lib/woods/extractors/callback_analyzer.rb
Overview
Analyzes callback method bodies to detect side effects.
Given a model’s composite source code (with inlined concerns) and its callback metadata, this analyzer finds each callback method body and classifies its side effects: column writes, job enqueues, service calls, mailer triggers, and database reads.
Constant Summary collapse
- DB_READ_METHODS =
Database query methods that indicate a read operation.
%w[find where pluck first last].freeze
- SINGLE_COLUMN_WRITERS =
Methods that write a single column, taking column name as first argument.
%w[update_column write_attribute].freeze
- MULTI_COLUMN_WRITERS =
Methods that write multiple columns via keyword arguments.
%w[update_columns assign_attributes].freeze
- ASYNC_METHODS =
Async enqueue methods that indicate a job is being dispatched.
%w[perform_later perform_async perform_in perform_at].freeze
- SINGLE_COLUMN_WRITER_PATTERNS =
Pre-compiled regex patterns (avoid dynamic regex construction in hot loops)
SINGLE_COLUMN_WRITERS.to_h do |w| [w, /\b#{Regexp.escape(w)}\s*\(?\s*[:'"](\w+)/] end.freeze
- MULTI_COLUMN_WRITER_PATTERNS =
MULTI_COLUMN_WRITERS.to_h do |w| [w, /\b#{Regexp.escape(w)}\s*\(([^)]+)\)/m] end.freeze
- ASYNC_PATTERN =
/(\w+(?:Job|Worker))\.(?:#{ASYNC_METHODS.map { |m| Regexp.escape(m) }.join('|')})/- DB_READ_PATTERNS =
DB_READ_METHODS.to_h do |m| [m, /\.#{Regexp.escape(m)}\b/] end.freeze
Instance Method Summary collapse
-
#analyze(callback_hash) ⇒ Hash
Analyze a single callback and enrich it with side-effect data.
-
#initialize(source_code:, column_names: []) ⇒ CallbackAnalyzer
constructor
A new instance of CallbackAnalyzer.
Constructor Details
#initialize(source_code:, column_names: []) ⇒ CallbackAnalyzer
Returns a new instance of CallbackAnalyzer.
54 55 56 57 58 59 60 |
# File 'lib/woods/extractors/callback_analyzer.rb', line 54 def initialize(source_code:, column_names: []) @source_code = source_code @column_names = column_names.map(&:to_s) @parser = Ast::Parser.new @operation_extractor = FlowAnalysis::OperationExtractor.new @parsed_root = safe_parse end |
Instance Method Details
#analyze(callback_hash) ⇒ Hash
Analyze a single callback and enrich it with side-effect data.
Finds the callback’s method body in the source, scans it for side effects, and returns the original callback hash with an added :side_effects key.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/woods/extractors/callback_analyzer.rb', line 71 def analyze(callback_hash) filter = callback_hash[:filter].to_s method_node = find_method_node(filter) return callback_hash.merge(side_effects: empty_side_effects) if method_node.nil? method_source = method_source_from_node(method_node) return callback_hash.merge(side_effects: empty_side_effects) if method_source.nil? callback_hash.merge( side_effects: { columns_written: detect_columns_written(method_source), jobs_enqueued: detect_jobs_enqueued(method_source), services_called: detect_services_called(method_source), mailers_triggered: detect_mailers_triggered(method_source), database_reads: detect_database_reads(method_source), operations: extract_operations(method_node) } ) end |