Module: Arca::Collector
- Defined in:
- lib/arca/collector.rb
Overview
Include Arca::Collector in an ActiveRecord class in order to collect data about how callbacks are being used.
Class Method Summary collapse
Class Method Details
.included(base) ⇒ Object
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/arca/collector.rb', line 17 def self.included(base) base.class_eval do define_singleton_method(:arca_callback_data) do @arca_callback_data ||= Hash.new {|k,v| k[v] = [] } end # Find the callback methods defined on this class. callback_method_symbols = singleton_methods.grep /^(after|around|before)\_/ callback_method_symbols.each do |callback_symbol| # Find the UnboundMethod for the callback. callback_method = singleton_class.instance_method(callback_symbol) # Redefine the callback method so that data can be collected each time # the callback is used for this class. define_singleton_method(callback_method.name) do |*args, &block| # Duplicate args before modifying. args_copy = args.dup # Add target_symbol :inline to args_copy if a block, Proc, or Class # was given. if block args_copy.unshift(:inline) elsif args_copy.first.kind_of?(Proc) args_copy.shift args_copy.unshift(:inline) elsif !args_copy.first.kind_of?(Symbol) class_or_instance = args_copy.shift if class_or_instance.class == Class args_copy.unshift(class_or_instance.name.to_sym) else args_copy.unshift(class_or_instance.class.name.to_sym) end end # Get the options hash from the end of the args Array if it exists. = args_copy.pop if args[-1].is_a?(Hash) # Get the callback file path and line number from the caller stack. callback_file_path, callback_line_number = ARCA_CALLBACK_FINDER_REGEXP.match(caller.first)[1..2] # Extract the model file path from the caller stack. caller.each do |line| if match = /\A(.+):\d+:in\s`<class:#{name.split("::").last}>'/.match(line) self.arca_callback_data[:model_file_path] = match[1] break end end # Iterate through the rest of the args. Each remaining arguement is # a Symbol representing the callback target method. args_copy.each do |target_symbol| # Find the conditional symbol if it exists in the options hash. conditional_symbol = ARCA_CONDITIONALS. find {|conditional| && .has_key?(conditional) } # Find the conditional target symbol if there is a conditional. conditional_target_symbol = if conditional_symbol [conditional_symbol] end # Set the collector hash for this callback_symbol to an empty # Array if it has not already been set. arca_callback_data[callback_symbol] ||= [] # Add the collected callback data to the collector Array for # this callback_symbol. arca_callback_data[callback_symbol] << { :callback_symbol => callback_symbol, :callback_file_path => callback_file_path, :callback_line_number => callback_line_number.to_i, :target_symbol => target_symbol, :conditional_symbol => conditional_symbol, :conditional_target_symbol => conditional_target_symbol } end # Bind the callback method to self and call it with args. callback_method.bind(self).call(*args, &block) end end end end |