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

前端 未结 6 1328
悲&欢浪女
悲&欢浪女 2020-12-14 18:39

I\'m monkey-patching a Rails engine with something like:

SomeClass.class_eval do
  # ...
end

The first time I hit the web site, on developm

相关标签:
6条回答
  • 2020-12-14 19:05

    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

    0 讨论(0)
  • 2020-12-14 19:09

    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.

    0 讨论(0)
  • 2020-12-14 19:12

    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.

    0 讨论(0)
  • 2020-12-14 19:12

    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'

    0 讨论(0)
  • 2020-12-14 19:18

    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.

    0 讨论(0)
  • 2020-12-14 19:27

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

    0 讨论(0)
提交回复
热议问题