我正在探索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这可以做到吗?如果可以,如何做到?
更新:感谢下面的Tom和Pavel。挑战的一部分,是我正在构建一个第三方gem,它将分析主机应用程序的所有SQL返回,而不需要修改他们的代码。基本上,将它插入到Gemfile中,进行捆绑,然后就可以了。
我正在考虑extending ActiveRecord::Base和using the method append_info_to_payload,但到目前为止还没有在gem中工作过。
例如,我想重写ActiveRecord::Querying find_by_sql()方法的有效负载,如下所示:
payload = {
record_count: result_set.length,
class_name: name,
result_set: result_set
}在测试和手动编辑我本地的ActiveRecord gem时,这将通过ActiveSupport::Notifications发布/订阅提供完整的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我将其添加到我的gem的initializer.rb文件中。
最后:我在ActiveRecord上创建了两个拉请求,让result_set在有效负载中向前传递,以便在ActiveSupport::Notifications:querying.rb和join_dependency.rb中使用。
发布于 2018-12-12 17:31:35
发布于 2018-12-13 06:01:49
您可以使用::instrument创建custom hook。然后,您可以定义具有status、result_set等的有效负载,并在块中定义它们的行为。
您可以在::instrument和::subscribe here上找到更多可靠的文档。
编辑:我更深入地了解了这一点,偶然发现了this stack overflow question。看起来append_info_to_payload方法就是您要找的。它已经被移到了private method is Rails 5。
https://stackoverflow.com/questions/53602951
复制相似问题