扩展ActiveSupport :: Notifications.subscribe,instantiation.active_record挂钩

Mar*_*mer 6 ruby notifications activerecord instantiation activesupport

我正在探索ActiveSupport::Notifications,并希望了解更多信息'instantiation.active_record',而不仅仅是:record_count:class_name [1].例如,

ActiveSupport::Notifications.subscribe /instantiation.active_record/ do |*args|

  args.status #Database or ActiveRecord return status
  args.result #The actual result set returned
  args.etc .. #Any other info I can collect on the event

  # Additional code ...
end
Run Code Online (Sandbox Code Playgroud)

可以这样做,如果是这样,怎么办?

更新:感谢Tom和Pavel.部分挑战是,我正在构建第三方gem,它将分析主机应用程序的所有SQL返回,而无需修改其代码.基本上,将它插入Gemfile,做一个捆绑,然后离开.

我正在考虑扩展ActiveRecord :: Base,并使用方法append_info_to_payload,但到目前为止还没有在gem中工作.

作为一个例子,我想覆盖ActiveRecord :: Querying find_by_sql()方法的有效负载,如下所示:

payload = {
  record_count: result_set.length,
  class_name: name,
  result_set: result_set
}
Run Code Online (Sandbox Code Playgroud)

在测试和手动编辑我的本地ActiveRecord gem时,它通过ActiveSupport :: Notifications pub/sub提供完整的result_set.

答:所以,答案是使用该class_eval方法,并在ActiveRecord :: Querying中覆盖find_by_sql方法:

ActiveRecord::Querying.class_eval do
  def find_by_sql(sql, binds = [], preparable: nil, &block)
    result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
    column_types = result_set.column_types.dup
    columns_hash.each_key { |k| column_types.delete k }
    message_bus = ActiveSupport::Notifications.instrumenter

    payload = {
        record_count: result_set.length,
        class_name: name,
        result_set: result_set
    }

    message_bus.instrument("instantiation.active_record", payload) do
      result_set.map { |record| instantiate(record, column_types, &block) }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我把它添加到我的gem initializer.rb文件中.

决赛:我创建了ActiveRecord的两个下拉请求,有result_set向前传递的有效载荷中的ActiveSupport ::通知用途:querying.rbjoin_dependency.rb.

Pav*_*yuk 1

这可以做到吗?如果可以,如何做到?

我不这么认为。

看看这个这个- 在这两种情况下都是只有和选项payload的哈希。除指南中所述外,没有其他选项。record_countclass_name