我有一个引擎,它在其初始化器中扩展另一个引擎类,如下所示:
module MyApp
class Engine < ::Rails::Engine
initializer 'extend Product' do
AnotherApp::Product.send :include, MyApp::ProductExtender
end
end
end
ProductExtender
模块在包含它时调用AnotherApp :: Product上的一些方法,例如
module ProductExtender
def self.included( model )
model.send :include, MethodsToCall
end
module MethodsToCall
def self.included( m )
m.has_many :variations
end
end
end
这适用于测试和生产环境,但是当config.cache_classes = false
时,当我尝试调用ProductExtender定义的内容时,它会向我抛出NoMethodError
,例如@ product.variations。
毋庸置疑,看到我的所有测试都通过,然后在开发过程中遇到错误,这是令人不寒而栗的。当我设置cache_classes = true
时,它不会发生,但它让我想知道我是否正在做一些我不应该做的事情。
我的问题有两个:为什么会发生这种情况,是否有更好的方法来实现在另一个应用程序对象上扩展/调用方法的功能?
全部谢谢!
答案 0 :(得分:4)
我设法使用to_prepare
块而不是初始化程序来解决此问题。 to_prepare
块在生产中和开发中的每个请求之前执行一次,因此似乎满足了我们的需求。
我在研究Rails::Engine
时并不明显,因为它是从Rails::Railtie::Configuration
继承而来的。
所以不是问题中的代码,我会:
module MyApp
class Engine < ::Rails::Engine
config.to_prepare do
AnotherApp::Product.send :include, MyApp::ProductExtender
end
end
end
答案 1 :(得分:0)
cache_classes实际上有一个误导性的名称:没有涉及缓存。如果将此选项设置为false,则rails会显式卸载您的应用程序代码并在需要时重新加载它。这使您在开发中所做的更改无需重新启动(服务器)进程即可生效。
在您的情况下,像ProductExtender一样重新加载AnotherApp :: Product,但重新加载后初始化程序不会再次触发,因此AnotherApp :: Product不会“扩展”。
我非常了解这个问题,最终运行了我的开发环境,其中cache_classes = true并偶尔重启我的服务器。我没有那么多关于引擎/插件的开发,所以这是最简单的方法。