在为我的Rails应用程序构建ruby gem时遇到了类重载问题。
背景
在gem中,我有以下类定义
module MyGem
class AppConfigBase
def app_title
"Title Missing"
end
end
end
在Rails应用程序中,我创建了一个config/my_gem.rb
文件来保存一些特定于应用程序的覆盖。 (我的目标是让gem的用户定义一些信息,但在超类中有一些默认值。)
module MyGem
class AppConfig < AppConfigBase
def app_title
"Great App"
end
end
end
在gem内部的某个时刻,我调用MyGem::AppConfig.new.app_title
并收到正确的字符串。耶!
接下来,我决定推动信封:我希望自动加载工作,这样开发人员每次更改此文件时都不必重启rails服务器。
我首先试着看看Rails是否已经设置好了。我从app_title
课程中删除了AppConfig
方法。当我重新加载页面时,我仍然返回“Great App”字符串。 :( Rails没有重新加载config/my_gem.rb
(或配置目录中的任何内容),所以这是预期的结果。
接下来,我尝试添加以下初始化程序:
if Rails.env.development?
ActionDispatch::Callbacks.after do
load "#{Rails.root}/config/my_gem.rb"
end
end
上面的初始化程序部分地解决了这个问题,但我想理解为什么它不能完全解决问题。有了初始化程序,
app_title
方法,我仍然得到错误的字符串(子类方法中的那个...不再存在)。因此,当我添加方法时,初始化程序中的加载调用似乎会拾取新方法。但是,如果我删除一个方法,它似乎没有帮助。
config/my_gem/my_gem.rb
,然后将config/my_gem
添加到Rails中的自动加载路径,但我不想创建这个额外的目录只是得到一些东西自动加载。)答案 0 :(得分:1)
这不是自动加载的工作原理。 Rails的重新加载器(不同于,但取决于自动加载器机制)通过取消定义常量,然后通过要求定义它们的文件来重新创建它们。你真正想要的是标记常数unloadable。在你的覆盖中:
module MyGem
class AppConfig < AppConfigBase
unloadable
def app_title
"Great App"
end
end
end
这会将常量添加到每个请求要卸载的常量列表中,但它也期望它可以通过加载my_gem/app_config.rb
并期望它来加载常量在你的负载路径上。出于这个原因,这种覆盖通常发生在lib/
而不是config/
中,因为前者在您的加载路径中而后者不在。{1}}中。它也意味着除了那些使用它之外的任何请求可能不需要该常量。
通常情况下,更改config
中的文件需要重新启动才能应用。