事实证明,Spring缓存了我非常简单的监听器方法(我写的是非常简单的引擎)。
示例:
应用/模型/ 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重启我的意思是手动执行spring stop
命令,这真的很烦人。
更神秘的是,我可能会将another_method
返回值更改为false,然后测试失败,这是正常的,但当我更改after_something
方法正文时,请说return false
它没有&# 39; t对测试有任何影响(比如after_something
的主体以某种方式缓存)。
这不是高优先级问题,因为这种奇怪的行为只在侦听器方法体内可见,并且通过将所有逻辑移动到类中的另一个方法很容易克服。无论如何,它可能会让人感到困惑(特别是在开始的时候,我并不知道确切的问题)。
答案 0 :(得分:3)
问题是正确引起的,因为当您全局订阅一个侦听器时,即使重新加载了它的类,该对象仍保留在内存中,指向它最初构造的类,即使该类已在此期间重新加载。 / p>
在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
将清除所有订阅者,因此如果您在多个引擎中具有与上述类似的代码,则只有最后一个要加载的引擎才会订阅其侦听器。