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.