我在我的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
但我只是不知道该把它放在哪里。
更新
根据答案,我使用以下代码创建了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
但这会导致每个Devise操作出错:
路由错误:未定义的方法'prepend_before_filter' 设计:: SessionsController:类
答案 0 :(得分:57)
如果您尝试重新打开一个类,它的语法与声明一个新类的语法相同:
class DeviseController
end
如果在真正的类声明之前执行此代码,它将继承自Object,而不是扩展Devise声明的类。相反,我尝试使用以下
DeviseController.class_eval do
# Your new methods here
end
这样,如果尚未声明DeviseController
,您将收到错误消息。结果,你可能最终得到
require 'devise/app/controllers/devise_controller'
DeviseController.class_eval do
# Your new methods here
end
答案 1 :(得分:12)
使用Rails 4 @aceofspades的答案对我不起作用。
我一直要求':cannot load such file -- devise/app/controllers/devise_controller (LoadError)
我没有使用require语句而是使用to_prepare
事件挂钩,而不是使用初始化器的加载顺序。它确保猴子修补在第一次请求之前发生。此效果类似于after_initialize
挂钩,但确保在重新加载后在开发模式下重新应用猴子补丁(在prod模式下结果相同)。
Rails.application.config.to_prepare do
DeviseController.class_eval do
# Your new methods here
end
end
N.B。 to_prepare
上的rails文档仍然不正确:请参阅此Github issue
答案 2 :(得分:3)
如何为flash哈希的属性添加覆盖初始值设定项和别名,如下所示:
class ActionDispatch::Flash::FlashHash
alias_attribute :success, :notice
alias_attribute :error, :alert
end
这应该允许你的应用程序读取flash [:notice]或flash [:success](flash.notice和flash.success)
答案 3 :(得分:3)
在初始化程序文件中:
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?
end
end
DeviseController.send(:include, DeviseControllerFlashMessage)
这很残酷但会做你想做的事。 mixin将删除先前的set_flash_message方法,强制子类回退到mixin方法。
编辑: 当mixin包含在类中时调用self.included。 klass参数是包含mixin的Class。在这种情况下,klass是DeviseController,我们在其上调用remove_method。
答案 4 :(得分:1)
您需要覆盖DeviseController,同时在初始化程序中保留其超类。
类似的东西:
class DeviseController < Devise.parent_controller.constantize
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
答案 5 :(得分:0)
这是你想要初始化rails文件夹的那种东西,因为它特别是这个应用程序的自定义配置,其次你应该这样使用:
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
然后你应该得到预期的行为。 希望它有所帮助,因为我没有测试过,请不要给予反馈,我会帮你尝试不同的东西。
答案 6 :(得分:0)
我知道这是一个旧线程,但这可能仍然有用。您应该能够使用引擎called_from path来要求gem目录中的文件。
require File.expand_path('../../app/helpers/devise_helper',Devise::Engine.called_from) require File.expand_path('../../app/controllers/devise_controller',Devise::Engine.called_from) DeviseController.class_eval do # Your new methods here end