如何修补在Rails中自动加载的代码?

时间:2010-12-16 12:35:08

标签: ruby-on-rails monkeypatching ruby-on-rails-2

我正在使用类似的东西修补Rails引擎:

SomeClass.class_eval do
  # ...
end

我第一次访问网站时,至少在开发模式下,它可以工作,但第二次就像我的补丁一样从未存在过。我认为它是Rails自动重新加载引擎(安装在vendor /中)而不是重新加载我的代码。这是Rails 2.3。

有什么想法可以让我的代码重新加载吗?

6 个答案:

答案 0 :(得分:20)

编辑:此解决方案仅适用于Rails 3+,因为它依赖于Rails :: Railtie中的某些功能。将此代码放在初始化程序中。

这个问题很老了,但我发现这是一个解决方案:

Rails.configuration.to_prepare do
  SomeClass.class_eval do
    # ...
  end
end

这迫使Rails在开发模式下的每个请求上重新加载类,但只在生产中重新加载一次。

答案 1 :(得分:7)

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

  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'

答案 2 :(得分:5)

如果将补丁放在/ config / initializers中的任何.rb文件中,它应该可以工作。

答案 3 :(得分:0)

不幸的是,没有办法挂钩Rails 2.x的重载机制。 您可以做的是将补丁放在app或lib目录中的某个位置。 (lib/core_ext可能是首选位置)。然后将目录添加到配置中的autoload_paths。

您可能还需要打开该类,而不是使用class_eval。

答案 4 :(得分:0)

这很丑陋,但我发现如果我将这种代码放在environment.rb的底部,它始终保证在启动时正确的加载顺序。

答案 5 :(得分:0)

看看这颗宝石如何处理"装饰"又称猴子在引擎中修补东西,反之亦然:

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