Monkey patching Devise (or any Rails gem)
Używam gem uwierzytelnianiaDevise w moim projekcie Rails i chcę zmienić klucze, których używa w alertach flash. (Devise używa klawiszy :notice i: alert flash, ale chcę je zmienić na: success I: error, aby móc wyświetlać ładne zielone / czerwone pola z Bootstrap .)
Więc chcę być w stanie jakoś nadpisać metodę set_flash_message
w DeviseController .
Oto nowa metoda:
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
Ale nie wiem, gdzie to umieścić.
UPDATE:
Na podstawie odpowiedzi utworzyłem config/initializers / overrides.plik rb o następującym kodzie:
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
Ale to powoduje błąd przy każdej akcji Devise:
Routing Error: undefined method 'prepend_before_filter' for Devise:: SessionsController:Class
7 answers
Jeśli spróbujesz ponownie otworzyć klasę, będzie to taka sama składnia jak deklarowanie nowej klasy:
class DeviseController
end
Jeśli ten kod jest wykonywany przed rzeczywistą deklaracją klasy, dziedziczy po obiekcie zamiast rozszerzać klasę zadeklarowaną przez Devise. Zamiast tego staram się użyć następującego
DeviseController.class_eval do
# Your new methods here
end
W ten sposób otrzymasz błąd, jeśli DeviseController
nie został zadeklarowany. W rezultacie prawdopodobnie skończysz z
require 'devise/app/controllers/devise_controller'
DeviseController.class_eval do
# Your new methods here
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 17:49:54
Używanie Rails 4 @ aceofspades answer Nie działało dla mnie.
/ Align = "left" / ':cannot load such file -- devise/app/controllers/devise_controller (LoadError)
Zamiast obijać się o kolejność ładowania inicjalizatorów użyłem Hooka to_prepare
zdarzenia bez instrukcji require. Zapewnia to, że łatanie małp odbywa się przed pierwszym żądaniem. Efekt ten jest podobny do Hooka after_initialize
, ale zapewnia, że monkey patching jest ponownie stosowany w trybie deweloperskim po przeładowaniu (w trybie prod wynik jest identyczny).
Rails.application.config.to_prepare do
DeviseController.class_eval do
# Your new methods here
end
end
N. B. szyny dokumentacja na {[2] } jest nadal Niepoprawna: zobacz ten problem z Githubem
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-30 22:07:19
A co z dodaniem w nadpisywaniu inicjalizatora i aliasu dla atrybutów hasha Flasha, jak to:
class ActionDispatch::Flash::FlashHash
alias_attribute :success, :notice
alias_attribute :error, :alert
end
To powinno pozwolić Twojej aplikacji odczytać flash [: notice] lub flash[:success] (flash.uwaga i błysk.sukces)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 17:14:35
W pliku inicjalizatora:
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)
To dość brutalne, ale zrobi to, co chcesz.
Mixin usunie poprzednią metodę set_flash_message, zmuszając podklasy do powrotu do metody mixin.
Edytuj: siebie.included jest wywoływany, gdy mixin jest zawarty w klasie. Parametr klass jest klasą, do której włączono mixin. W tym przypadku klass jest Devisecontrollerem i wywołujemy na nim remove_method.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 14:53:56
Musisz nadpisać DeviseController, zachowując jego superklasę w swoim inicjalizatorze.
Coś w stylu:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-18 20:46:31
Jest to coś, co chcesz umieścić w folderze initialize rails, ponieważ jest to niestandardowa konfiguracja dla tej aplikacji, po drugie powinieneś użyć tak:
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
Następnie należy uzyskać oczekiwane zachowanie. mam nadzieję, że to pomaga, ponieważ nie testowałem, nie pls daj opinię, a ja pomogę ci spróbować czegoś innego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-16 14:52:29
Wiem, że to stary wątek, ale to może być pomocne. Powinieneś być w stanie zażądać pliku z katalogu gem przy użyciu silnika o nazwie path_from.
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 23:02:41