1

事实证明,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)

app/observers/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某种方式缓存的主体)。

这不是高优先级问题,因为这种奇怪的行为仅在侦听器方法体内可见,并且通过将所有逻辑移动到类中的另一个方法很容易克服。无论如何,它可能会令人困惑(尤其是在我不知道确切问题的开始时)。

4

1 回答 1

3

问题是正确引起的,因为当您全局订阅侦听器时,即使重新加载其类,对象仍保留在内存中,指向最初构造它的类,即使同时重新加载了该类。

试试这个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将清除所有订阅者,因此如果您在多个引擎中具有与上述类似的代码,则只有最后一个要加载的引擎才会订阅其侦听器。

于 2016-04-28T08:16:36.257 回答