20

我正在用类似的东西给 Rails 引擎打补丁:

SomeClass.class_eval do
  # ...
end

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

任何想法如何做到这一点,以便我的代码也被重新加载?

4

6 回答 6

28

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

这个问题很老了,但这是我找到的解决方案:

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

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

于 2011-10-06T04:18:02.150 回答
9

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

  1. 将您的扩展名放在lib/ext/. (由#rubyonrails IRC 房间的资深workmad3 建议。) 在我的例子中,我正在向Mail::Message类添加一个方法(来自mailActionMailer 使用的gem),所以我创建了:

    /lib/ext/mail/message.rb

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

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

  3. 创建一个初始化程序来加载你所有的猴子补丁。Rails 将在引用常量时自动加载文件,但是由于您正在向现有类/模块添加方法而不是定义新方法,因此这不起作用,因此您必须手动要求所有猴子补丁。所以我创建了:

    /config/initializers/monkey_patches.rb

    其中包含:

    require 'ext/mail/message'

于 2014-04-14T17:52:32.027 回答
5

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

于 2011-06-07T13:05:04.070 回答
0

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

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

于 2010-12-16T12:51:05.750 回答
0

这很难看,但我发现如果我把这种代码放在 environment.rb 的底部,它总是能保证启动时正确的加载顺序。

于 2011-06-12T12:35:39.197 回答
0

看看这个 gem 如何处理“装饰”,也就是猴子修补引擎中的东西,反之亦然:

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

于 2015-06-12T23:23:39.307 回答