如何在Rails中自动加载猴子补丁代码?
我正在修补一个Rails引擎,例如:
SomeClass.class_eval do # ... end
我第一次访问网站时,至少在开发模式下,它可以工作,但第二次就像我的补丁从未存在过。 我认为它是Rails自动重新加载引擎(安装在vendor /中)而不是重新加载我的代码。 这是Rails 2.3。
任何想法如何做到这样我的代码也被重新加载?
编辑:此解决方案仅适用于Rails 3+,因为它依赖于Rails :: Railtie中的某些function。 将此代码放在初始化程序中。
这个问题很老了,但我发现这是一个解决方案:
Rails.configuration.to_prepare do SomeClass.class_eval do # ... end end
这迫使Rails在开发模式中的每个请求上重新加载类,但只在生产中重新加载一次。
我刚刚编写了我的第一个猴子补丁,因此需要围绕它提出一系列约定。 这就是我想出的:
-
将扩展名放在
lib/ext/
。 (由#rubyonrails IRC会议室中的资深workmad3建议。)在我的情况下,我正在向Mail::Message
类添加一个方法(来自mail
gem,由ActionMailer使用),所以我创建了:/lib/ext/mail/message.rb
-
打开类或模块并添加代码:
module Mail class Message def to_is_phone? !!(self.to.first =~ /^\+1\d{10}$/) end end end
-
创建一个initalizer来加载你所有的猴子补丁。 Rails会在引用常量时自动加载文件,但由于您要向现有类/模块添加方法而不是定义新方法,因此无法正常工作,因此您必须手动要求所有的猴子补丁。 所以我创建了:
/config/initializers/monkey_patches.rb
其中包含:
require 'ext/mail/message'
如果将补丁放在/ config / initializers中的任何.rb文件中,它应该可以工作。
不幸的是,没有办法挂钩Rails 2.x的重载机制。 您可以做的是将补丁放在app或lib目录中的某个位置。 ( lib/core_ext
可能是首选位置)。 然后将目录添加到配置中的autoload_paths。
您可能还需要打开该类,而不是使用class_eval。
这很丑陋,但我发现如果我将这种代码放在environment.rb的底部,它始终保证启动时正确的加载顺序。
看看这个gem如何处理“装饰”又称猴子在引擎中修补东西,反之亦然: