Search code examples
ruby-on-railsrubydeviserubygemsmonkeypatching

Monkey patching Devise (or any Rails gem)


I'm using the Devise authentication gem in my Rails project, and I want to change the keys it's using in flash alerts. (Devise uses :notice and :alert flash keys, but I want to change them to :success and :error so that I can display nice green/red boxes with Bootstrap.)

So I want to be able to somehow override the set_flash_message method in DeviseController.

Here's the new method:

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?

end

But I just don't know where to put it.


UPDATE:

Based on an answer I created a config/initializers/overrides.rb file with the following code:

class DeviseController
    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?
    end
end

But this causes an error on every Devise action:

Routing Error: undefined method 'prepend_before_filter' for Devise::SessionsController:Class


Solution

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

    class DeviseController
    end
    

    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 here
    end
    

    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 here
    end