Monkey patching Devise (or any Rails gem) Monkey patching Devise (or any Rails gem) ruby ruby

Monkey patching Devise (or any Rails gem)


If you try to reopen a class, it's the same syntax as declaring a new class:

class DeviseControllerend

If this code is executed before the real class declaration, it inherits from Object instead of extending the class declared by Devise. Instead I try to use the following

DeviseController.class_eval do  # Your new methods hereend

This way, you'll get an error if DeviseController has not been declared. As a result, you'll probably end up with

require 'devise/app/controllers/devise_controller'DeviseController.class_eval do  # Your new methods hereend


Using Rails 4 @aceofspades answer didn't work for me.

I kept getting require': cannot load such file -- devise/app/controllers/devise_controller (LoadError)

Instead of screwing around with load order of initializers I used the to_prepare event hook without a require statement. It ensures that the monkey patching happens before the first request. This effect is similar to after_initialize hook, but ensures that monkey patching is reapplied in development mode after a reload (in prod mode the result is identical).

Rails.application.config.to_prepare do  DeviseController.class_eval do    # Your new methods here  endend

N.B. the rails documentation on to_prepare is still incorrect: See this Github issue


In your initializer file :

module DeviseControllerFlashMessage  # This method is called when this mixin is included  def self.included klass    # klass here is our DeviseController    klass.class_eval do      remove_method :set_flash_message    end  end  protected   def set_flash_message(key, kind, options = {})    if key == 'alert'      key = 'error'    elsif key == 'notice'      key = 'success'    end    message = find_message(kind, options)    flash[key] = message if message.present?  endendDeviseController.send(:include, DeviseControllerFlashMessage)

This is pretty brutal but will do what you want.The mixin will delete the previous set_flash_message method forcing the subclasses to fall back to the mixin method.

Edit:self.included is called when the mixin is included in a class. The klass parameter is the Class to which the mixin has been included. In this case, klass is DeviseController, and we call remove_method on it.