2016-04-27 3 views
1

Оказывается, Spring использует мой метод прослушивания в wisper (я пишу довольно простой движок).Rails 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 возвращаемое значение ложно, а затем испытания в противном случае это нормально, но когда я изменяю after_something тело метода, чтобы сказать return false это не оказывает никакого влияния на тесты (как тело after_something как-то кэширован).

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

ответ

2

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

Попробуйте это в 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 очистит всех подписчиков, поэтому, если у вас есть аналогичный код, как указано выше в нескольких двигателях, только последний загружаемый движок будет иметь подписчиков.

+0

Благодарим за быстрый ответ. В моем случае мне нужно изменить вторую строку на 'Wsper.clear, если Rails.env.development? || Rails.env.test? '. Что касается 'Wisper.clear', я предполагаю, что этого будет достаточно, чтобы добавить его только в основной движок, который будет/должен быть загружен первым. – jmarceli

+0

Да, хорошая точка, если '' Wisper.clear 'добавлен только к первому движку, это должно хорошо работать :) – Kris

Смежные вопросы