猴子修补Devise(或任何Rails gem)

Yar*_*rin 21 ruby rubygems monkeypatching ruby-on-rails devise

我在我的Rails项目中使用Devise身份验证gem,我想更改它在闪存警报中使用的密钥.(设计使用:通知和:警告闪存键,但我想将它们更改为:成功和:错误,以便我可以使用Bootstrap显示漂亮的绿色/红色框.)

所以我希望能够以某种方式覆盖DeviseController中set_flash_message方法.

这是新方法:

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
Run Code Online (Sandbox Code Playgroud)

但我只是不知道该把它放在哪里.


更新:

基于答案,我使用以下代码创建了config/initializers/overrides.rb文件:

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
Run Code Online (Sandbox Code Playgroud)

但这会导致每个Devise操作出错:

路由错误:Devise :: SessionsController:Class的未定义方法'prepend_before_filter'

ace*_*des 57

如果您尝试重新打开一个类,则它与声明一个新类的语法相同:

class DeviseController
end
Run Code Online (Sandbox Code Playgroud)

如果此代码在实际类声明之前执行,则它继承自Object而不是扩展Devise声明的类.相反,我尝试使用以下内容

DeviseController.class_eval do
  # Your new methods here
end
Run Code Online (Sandbox Code Playgroud)

这样,如果DeviseController尚未声明,您将收到错误.结果,你可能会最终得到

require 'devise/app/controllers/devise_controller'

DeviseController.class_eval do
  # Your new methods here
end
Run Code Online (Sandbox Code Playgroud)


ARO*_*ARO 14

使用Rails 4 @aceofspades的答案对我不起作用.

我一直要求': cannot load such file -- devise/app/controllers/devise_controller (LoadError)

to_prepare没有使用require语句使用事件挂钩,而是使用初始化器的加载顺序.它确保猴子修补在第一次请求之前发生.此效果类似于after_initializehook,但确保在重新加载后在开发模式下重新应用猴子修补(在prod模式下结果相同).

Rails.application.config.to_prepare do
  DeviseController.class_eval do
    # Your new methods here
  end
end
Run Code Online (Sandbox Code Playgroud)

注意,rails文档to_prepare仍然不正确:请参阅此Github问题