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

pup*_*eno 15 monkeypatching ruby-on-rails ruby-on-rails-2

我正在修补一个Rails引擎,例如:

SomeClass.class_eval do
  # ...
end
Run Code Online (Sandbox Code Playgroud)

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

任何想法如何做到这样我的代码也被重新加载?

Jam*_*s H 20

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

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

Rails.configuration.to_prepare do
  SomeClass.class_eval do
    # ...
  end
end
Run Code Online (Sandbox Code Playgroud)

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

  • 也在 Rails 5 中为我工作。 (2认同)

odi*_*ity 8

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

  1. 放置您的扩展程序lib/ext/. (由#rubyonrails IRC房间的资深workmad3建议.) 在我的情况下,我在类中添加一个方法Mail::Message(来自mailgem,由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'

  • `monkey_patches.rb`可以改为`Dir [Rails.root.join('lib/ext/*.rb')].每个{|文件| 需要文件}`并且将拾取所有猴子补丁. (5认同)

小智 5

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


iai*_*ain 0

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

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