Rails spring wisper 监听器方法缓存
Rails spring wisper listener method caching
事实证明 Spring 缓存了我的 wisper 侦听器方法(我正在编写非常简单的引擎)。
示例:
app/models/myengine/my_class.rb
class Myengine::MyClass
include Wisper::Publisher
def something
# some logic
publish(:after_something, self)
end
end
config/initializers/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 重启我的意思是手动执行 spring stop
命令,这真的很烦人。
更神秘的是,我可能会将 another_method
return 值更改为 false,然后测试失败,这没关系,但是当我更改 after_something
方法体时,可以说 return false
它对测试没有任何影响(比如 after_something
的主体以某种方式被缓存)。
这不是高优先级问题,因为这种奇怪的行为只在侦听器方法体内可见,并且很容易通过将所有逻辑移动到 class 中的另一个方法来克服。无论如何,它可能会令人困惑(尤其是在一开始我不知道确切问题的时候)。
这个问题是正确的,因为当你全局订阅一个监听器时,即使它的 class 被重新加载,对象仍然在内存中指向它最初构造的 class ,即使class 已同时重新加载。
在 config/initializers/wisper.rb
试试这个:
Rails.application.config.to_prepare do
Wisper.clear if Rails.env.development?
Wisper.subscribe(Myengine::MyObserver.new)
end
to_prepare
将 运行 在开发环境的每个请求之前的块,但是一次,对于生产环境来说是正常的。因此,只要您的侦听器不保持任何状态,它就会按预期工作。
在我们从重新加载的 class 中重新订阅新实例之前,需要 Wisper.clear
删除订阅的现有侦听器。请注意 #clear
将清除所有订阅者,因此如果您在多个引擎中有与上述类似的代码,则只有最后一个要加载的引擎会订阅其侦听器。
事实证明 Spring 缓存了我的 wisper 侦听器方法(我正在编写非常简单的引擎)。
示例:
app/models/myengine/my_class.rb
class Myengine::MyClass
include Wisper::Publisher
def something
# some logic
publish(:after_something, self)
end
end
config/initializers/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 重启我的意思是手动执行 spring stop
命令,这真的很烦人。
更神秘的是,我可能会将 another_method
return 值更改为 false,然后测试失败,这没关系,但是当我更改 after_something
方法体时,可以说 return false
它对测试没有任何影响(比如 after_something
的主体以某种方式被缓存)。
这不是高优先级问题,因为这种奇怪的行为只在侦听器方法体内可见,并且很容易通过将所有逻辑移动到 class 中的另一个方法来克服。无论如何,它可能会令人困惑(尤其是在一开始我不知道确切问题的时候)。
这个问题是正确的,因为当你全局订阅一个监听器时,即使它的 class 被重新加载,对象仍然在内存中指向它最初构造的 class ,即使class 已同时重新加载。
在 config/initializers/wisper.rb
试试这个:
Rails.application.config.to_prepare do
Wisper.clear if Rails.env.development?
Wisper.subscribe(Myengine::MyObserver.new)
end
to_prepare
将 运行 在开发环境的每个请求之前的块,但是一次,对于生产环境来说是正常的。因此,只要您的侦听器不保持任何状态,它就会按预期工作。
在我们从重新加载的 class 中重新订阅新实例之前,需要 Wisper.clear
删除订阅的现有侦听器。请注意 #clear
将清除所有订阅者,因此如果您在多个引擎中有与上述类似的代码,则只有最后一个要加载的引擎会订阅其侦听器。