Расширение ActiveSupport :: Notifications.subscribe, instantiation.active_record ловушка - PullRequest
0 голосов
/ 04 декабря 2018

Я изучаю 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

Можно ли это сделать, и если да, то как?

Обновление: спасибо Тому и Павлу ниже.Часть проблемы заключается в том, что я создаю сторонний гем, который будет анализировать все SQL-запросы хост-приложения, не требуя изменения их кода.По сути, подключите его к Gemfile, сделайте пакет, и все готово.

Я рассматриваю расширение ActiveRecord :: Base и с использованием метода append_info_to_payload ,но пока что не работает ни в геме.

В качестве примера я хотел бы перезаписать полезную нагрузку метода ActiveRecord :: Querying find_by_sql (), чтобы это выглядело так:

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

При тестировании и ручном редактировании моего локального гема ActiveRecord это обеспечивает полный набор результатов через ActiveSupport :: Publishing / sub уведомлений.

Ответ: Итак, ответ заключается в использовании метода class_eval и перезаписи find_by_sqlметод в ActiveRecord :: Querying:

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

Я добавил это в файл initializer.rb моего драгоценного камня.

Final: я создал два вытягивающих запроса на ActiveRecord, чтобы передать результат result_set вполезная нагрузка для использования в ActiveSupport :: Уведомления: querying.rb и join_dependency.rb .

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Вы можете создать пользовательский хук с помощью ::instrument.Затем вы можете определить полезную нагрузку, которая имеет status, result_set и т. Д., И определить их поведение в блоке.

Более надежную документацию по ::instrument и ::subscribe можно найти здесь..

РЕДАКТИРОВАТЬ: Я изучил это больше и наткнулся на этот вопрос переполнения стека .Похоже, что метод append_info_to_payload это то, что вы ищете.Он был перенесен в приватный метод - это Rails 5.

Последнее редактирование: если вы чувствуете себя смелым, уведомление используется здесь и здесь , если вы хотите вставить свою дополнительную полезную нагрузку напрямую ?.

0 голосов
/ 12 декабря 2018

Можно ли это сделать, и если да, то как?

Я так не думаю.

Взгляните на это и this - в обоих случаях payload является хэшем с опциями record_count и class_name.Никаких дополнительных опций, кроме описанных в руководстве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...