如何在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在开发模式中的每个请求上重新加载类,但只在生产中重新加载一次。

我刚刚编写了我的第一个猴子补丁,因此需要围绕它提出一系列约定。 这就是我想出的:

  1. 将扩展名放在lib/ext/(由#rubyonrails IRC会议室中的资深workmad3建议。)在我的情况下,我正在向Mail::Message类添加一个方法(来自mail gem,由ActionMailer使用),所以我创建了:

    /lib/ext/mail/message.rb

  2. 打开类或模块并添加代码:

    module Mail class Message def to_is_phone? !!(self.to.first =~ /^\+1\d{10}$/) end end end

  3. 创建一个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如何处理“装饰”又称猴子在引擎中修补东西,反之亦然:

https://github.com/EPI-USE-Labs/activesupport-decorators