2012-10-26 93 views
4

有没有办法自动记录每次ActiveRecord回调发生?这将有助于追踪为什么某些事情发生时,记录有几个回调。跟踪/记录ActiveRecord回调

我想看到指出这消息被称为响应自动日志消息给回调,如:before_validation: calling update_capitalization

回答

2

谷歌和子孙后代(on Rails的3):

module CallbackTrace 
    def self.included kls 
    kls.send :alias_method_chain, :_compile_filter, :trace 
    end 

    def _compile_filter_with_trace filter 
    generated_code = _compile_filter_without_trace(filter) 
    return generated_code if filter.is_a?(Array) 
    method_name = generated_code.to_s.split(%r{\(|\s}).first 
    _klass = @klass 
    prelogger = ->{ 
     Rails.logger.info("START [#{filter.class}](#{generated_code})") 
     Rails.logger.info("#{_klass} #{Time.now}") 
     if imethod=(_klass.instance_method(method_name) rescue nil) 
      begin 
      Rails.logger.info(imethod.source) 
      rescue MethodSource::SourceNotFoundError 
      Rails.logger.info("NO SOURCE FOR #{generated_code}") 
      end 
     else 
      Rails.logger.info("NO METHOD: #{method_name} for #{@klass}") 
     end 
    } 
    postlogger = ->{ 
     Rails.logger.info("ENDED #{generated_code} #{Time.now}") 
    } 
    @klass.send :define_method, "prelogger_#{method_name}", &prelogger 
    @klass.send :define_method, "postlogger_#{method_name}", &postlogger 
    "(prelogger_#{method_name}; retval = retval = #{generated_code}; " + 
     "postlogger_#{method_name}; retval)" 
    end 
end 
ActiveSupport::Callbacks::Callback.send :include, CallbackTrace 
+0

这个代码文件应放在哪里?初始化器? –

+0

我把它放在一个带有配置选项的初始化程序中以运行它。效果很好。非常详细,所以即使在正常开发中也不会使用,但可以帮助您追踪奇怪的回调问题。 – mahemoff

+1

不幸的是,这不工作在Rails 4.1未定义的方法'_compile_filter'类'ActiveSupport :: Callbacks :: Callback'' – mahemoff

0

更简单的方法是使用本地的轨道记录方法:

Debugging Rails Applications

使用这样的:

logger.debug "Person attributes hash: #{@person.attributes.inspect}" 
logger.info "Processing the request..." 
logger.fatal "Terminating application, raised unrecoverable error!!!" 

编辑:

要检查什么叫当内容时发生异常也是有趣的使用

logger.error("trace: #{ex.backtrace().join("\n")}") 
+0

谢谢,但我正在寻找一种方式来自动执行它,也许是一个外部的宝石。我已经更新了这个问题。 – mahemoff

0

另一种方法它是定义所有模型上的回调记录。为了避免加载所有内容,您可以加载模型。为了简单起见,这将尝试加载与app/models/*.rb中的所有文件相对应的类。我也会使用puts,但你可以使用Rails.logger.info或其他。对于临时调试,你可以把它放入初始化程序,例如config/initializers/001_log_callbacks.rb

# Log all callbacks 
Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename| 
    name = File.basename(filename, '.rb') 
    begin 
    model = name.camelize.constantize 
    ActiveRecord::Callbacks::CALLBACKS.each do |callback| 
     if callback.to_s.start_with?('around_') 
     model.class_eval "#{callback} do |*args, &prc|; puts \"#{model}(\#{id}).#{callback} start\"; prc.call(*args) if prc; puts \"#{model}(\#{id}).#{callback} end\" end" 
     else 
     model.class_eval "#{callback} do; puts \"#{model}(\#{id}).#{callback}\" end" 
     end 
    end 
    rescue 
    end 
end