Rails Spring Wisper Слушатель Метод Кэширование

Оказывается, Spring кеширует мой метод прослушивания wisper (я пишу довольно простой движок).

Пример:

приложение / модели / myengine / my_class.rb

class Myengine::MyClass
  include Wisper::Publisher

  def something
    # some logic
    publish(:after_something, self)
  end
end

конфиг / Инициализаторы / wisper.rb

Wisper.subscribe(Myengine::MyObserver.new)

приложение / наблюдатели / myengine / my_observer.rb

class Myengine::MyObserver
  def after_something my_class_instance
    # any changes here requires Spring manual restart in order to be reflected in tests
    another_method
  end

  def another_method
    # all changes here or in any other class methods works ok with Spring and are instantly visible in tests
    return true
  end
end

Под весенним перезапуском я имею в виду ручное выполнение spring stop команда, которая действительно раздражает.

Что может быть более загадочным, я могу изменить another_method вернуть значение в false, а затем тесты не пройдены, что нормально, но когда я изменяю after_something метод тела, чтобы сказать return false это не оказывает никакого влияния на тесты (например, тело after_something как-то кешируется).

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

1 ответ

Решение

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

Попробуйте это в config/initializers/wisper.rb:

Rails.application.config.to_prepare do
  Wisper.clear if Rails.env.development?
  Wisper.subscribe(Myengine::MyObserver.new)
end

to_prepare будет запускать блок перед каждым запросом среды разработки, но один раз, как обычно для производственной среды. Поэтому, если ваш слушатель не поддерживает какое-либо состояние, он должен работать должным образом.

Wisper.clear необходимо удалить существующие подписчики подписчиков, прежде чем мы повторно подписать новый экземпляр из перезагруженного класса. Быть в курсе, что #clear удалит всех подписчиков, поэтому, если у вас есть код, подобный приведенному выше, в более чем одном движке, только последний загруженный механизм будет подписан на своих слушателей.

Другие вопросы по тегам