How to monkey-patch code that gets auto-loaded in Rails?

余生颓废 提交于 2019-11-28 21:26:20

EDIT: This solution only works for Rails 3+ since it's dependent on some functionality in Rails::Railtie. Put this code in an initializer.

This question is quite old, but here's a solution I found:

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

This forces Rails to reload the class on every request in development mode, but only once in production.

I just wrote my first monkey-patch, and so needed to come up with a set of conventions around it. Here's what I came up with:

  1. Place your extensions under lib/ext/. (Suggested by veteran workmad3 in #rubyonrails IRC room.) In my case, I'm adding a method to the Mail::Message class (from the mail gem, used by ActionMailer), so I created:

    /lib/ext/mail/message.rb

  2. Open the class or module and add your code:

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

  3. Create an initalizer to load all your monkey-patches. Rails will autoload a file when a constant is referenced, but since you're adding methods to existing classes/modules rather than defining new ones, that won't work, so you have to manually require all your monkey-patches. So I created:

    /config/initializers/monkey_patches.rb

    Which contains:

    require 'ext/mail/message'

If you place the patch in any .rb file inside /config/initializers, it should work.

Unfortunately, there is no way to hook into the reloading mechanism of Rails 2.x. What you could do, is place your patch somewhere in the app or lib directory. (lib/core_ext is probably the preferred location). Then add the directory to the autoload_paths in your config.

You might also need to open the class, rather than using class_eval.

It's ugly, but I found that if I put this kind of code at the bottom of environments.rb it always guaranteed correct load-order on startup.

Have a look at how this gem handles "decorating" aka monkey patching something in an engine or vice versa:

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!