Динамическое создание экземпляра ActiveRecord Observer для нескольких моделей

В настоящий момент я пытаюсь разработать плагин / гем, который учитывает несколько моделей. В идеале, наблюдатель должен быть создан автоматически с помощью всего одного одноэлементного метода ...

class MyModel < ActiveRecord::Base

  # a class method like this will tell the observer to observe this model
    observe_me

end

Моим первоначальным подходом было определение методов класса, включенных в базу AR:

module ClassMethods

  def observe_me
    @observe_me = true
  end

  def should_observe_me?
    @observe_me
  end
end
ActiveRecord::Base.extend(ClassMethods)

А затем используйте это, чтобы определить, какие модели наблюдать в Observer:

class MyObserver < ActiveRecord::Observer

  # this should observe all models where should_observe_me? #=> true
  observe ActiveRecord::Base.descendants.select { |m| m.try(:should_observe_me?) }.map(&:model_name)

end

Проблема, с которой я сталкиваюсь, заключается в том, что наблюдатель загружается до того, как модели определены, поэтому ActiveRecord не имеет потомков, а MyObserver не знает, какие модели наблюдать.

Следующей моей попыткой было взломать ActiveRecord :: Base.observers и ActiveRecord :: Base.instantiate_observers, но безуспешно.

Итак, как есть на данный момент:

Наблюдатель определен, но не знает, какие модели наблюдать. Модели определены и помечаются как подлежащие наблюдению, но наблюдатель уже наблюдался.

Есть ли способ отложить загрузку наблюдателя до тех пор, пока модели не будут определены, или кто-то может придумать лучший подход к этой проблеме?


person bodacious    schedule 08.12.2010    source источник


Ответы (1)


@gavin: В Rails3 изменилась структура инициализации приложения - возможно, это ваша проблема.

Когда / как вы включаете модуль ClassMethods? ЕСЛИ вы используете Rails3, и ЕСЛИ вы добавили «require 'detect_me'» в $ ROOT / config / environment.rb, тогда вы увидите (неправильное) поведение, которое вы описываете.

Если это так, вместо этого создайте $ ROOT / config / initializers / my_extensions.rb и вставьте туда «require ...».

person fearless_fool    schedule 29.01.2011