son sobre sintaxis rails que las instalar gems gemas ejemplos comandos caracteristicas ruby-on-rails ruby devise rubygems monkeypatching

ruby on rails - sobre - Diseño de parches de mono(o cualquier gema de Rails)



sintaxis ruby on rails (7)

Estoy usando la gema de autenticación Devise en mi proyecto Rails, y quiero cambiar las claves que está usando en las alertas flash. (Devise usa: aviso y: teclas de flash de alerta, pero quiero cambiarlas a: éxito y: error para que pueda mostrar bonitos cuadros verdes / rojos con Bootstrap )

Así que quiero poder anular de alguna manera el método DeviseController en DeviseController .

Aquí está el nuevo método:

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

Pero simplemente no sé dónde ponerlo.

ACTUALIZAR:

Basándome en una respuesta, creé un archivo config / initializers / overrides.rb con el siguiente código:

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

Pero esto causa un error en cada acción de Devise:

Error de enrutamiento: método no definido ''prepend_before_filter'' para Devise :: SessionsController: Class


¿Qué hay de agregar el inicializador y el alias de anulación para los atributos del hash de flash, como esto:

class ActionDispatch::Flash::FlashHash alias_attribute :success, :notice alias_attribute :error, :alert end

Esto debería permitir que su aplicación lea flash [: notice] o flash [: success] (flash.notice y flash.success)


Debe sobrescribir DeviseController mientras se mantiene alrededor de su superclase, en su inicializador.

Algo como:

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


En su archivo de inicializador:

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)

Esto es bastante brutal pero hará lo que quieras. El mixin eliminará el método set_flash_message anterior, lo que obligará a las subclases a recurrir al método mixin.

Edición: self.included se llama cuando el mixin se incluye en una clase. El parámetro klass es la clase a la que se ha incluido la mezcla. En este caso, klass es DeviseController, y llamamos remove_method en él.


Este es el tipo de cosas que querrá poner en la carpeta de inicialización de rieles, ya que es una configuración personalizada para esta aplicación en particular, en segundo lugar, debe usar así:

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

entonces debería obtener el comportamiento esperado. Espero que ayude ya que no he probado, de no por favor dar una retroalimentación y le ayudaré a probar algo diferente.


Sé que este es un hilo antiguo, pero esto podría ser útil. Debería poder solicitar el archivo desde el directorio de gemas utilizando el motor llamado_de la ruta.

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


Si intenta reabrir una clase, es la misma sintaxis que declarar una nueva clase:

class DeviseController end

Si este código se ejecuta antes de la declaración de clase real, hereda de Object en lugar de extender la clase declarada por Devise. En su lugar trato de usar lo siguiente

DeviseController.class_eval do # Your new methods here end

De esta manera, obtendrá un error si DeviseController no ha sido declarado. Como resultado, probablemente terminará con

require ''devise/app/controllers/devise_controller'' DeviseController.class_eval do # Your new methods here end


Usar la respuesta de Rails 4 @aceofspades no me funcionó.

Seguí recibiendo ": cannot load such file -- devise/app/controllers/devise_controller (LoadError)

En lugar de atornillar con el orden de carga de los inicializadores, utilicé el gancho del evento to_prepare sin una declaración de requerimiento. Asegura que el parche del mono ocurra antes de la primera solicitud. Este efecto es similar a after_initialize hook, pero garantiza que los parches de mono se vuelvan a aplicar en el modo de desarrollo después de una recarga (en el modo prod, el resultado es idéntico).

Rails.application.config.to_prepare do DeviseController.class_eval do # Your new methods here end end

NB: la documentación de rieles en to_prepare sigue siendo incorrecta: consulte este problema de Github