我正在使用gem根据用户配置选项动态设置ActiveRecord模型(例如table_name
)的属性。
我有一个实现此目的的初始化程序。然而,我的问题是在开发模式下,这些类被重新加载,因此它们不会保持这些值的设置。
所以我想我会使用一个铁路来挂钩重新加载这些文件并在模型上再次运行我的配置。然而,我的问题是,铁路中的config.to_prepare
似乎在reload!
实际发生之前运行。我可以通过一些记录来证明这一点:
module MyMod
class Railtie < Rails::Railtie
config.to_prepare do
Rails.logger.debug("Contact object_id: #{Contact.object_id}")
end
end
end
如果我加载我的控制台,我会得到第一个日志:
Contact object_id: 2202692040
如果我检查Contact.object_id
它匹配:
Contact.object_id #=> 2202692040
然后我reload!
reload!
我的to_prepare
日志中的Rails记录器:
Contact object_id: 2202692040
所以它仍然有旧的object_id,但是当我在控制台中检查它时:
Contact.object_id #=> 2197355080
哪个是新加载的类对象id。
那么在重新加载文件后如何让to_prepare
运行?使用Rails 3.0.10
我也尝试将此操作手动附加到after_prepare
上的ActionDispatch::Callbacks
回调,如下所示:
initializer "apartment.init" do
ActionDispatch::Callbacks.set_callback(:prepare, :after) do
Rails.logger.debug("Contact object_id: #{Contact.object_id}")
end
end
它确实在config.to_prepare
之后运行回调,但它似乎仍然发生before
重新加载文件...我得到与上面相同的行为。
答案 0 :(得分:16)
编写一个初始化程序,如果cache_classes
为false
,则使用ActionDispatch::Reloader
设置运行gem安装例程的to_prepare
回调。
initializer 'foobar.install' do
if Rails.configuration.cache_classes
FooBar.install!
else
ActionDispatch::Reloader.to_prepare do
FooBar.install!
end
end
end
它在带有reload!
方法的控制台和Rack应用程序服务器中都可以正常工作。
答案 1 :(得分:0)
我相信Rails重新加载器只会解开常量。在应用程序中引用常量时,模型会重新加载自动加载。
在你的回调中,我认为你必须通过引用所有模型来手动触发负载。也许你的宝石可以保留包含它的所有模型的列表,然后只需引用常量来自动加载它们......
model_names.each { |model_name| model_name.constantize }
您可以使用self.included
构建列表:
module MyGem
self.included(base)
@model_names ||= Set.new
@model_names += base.to_s
end
end