5

Estoy actualizando mi plugin Rails para que sea un motor que funcione con la última versión 3.0RC1 y estoy teniendo problemas para encontrar la mejor (y la más correcta) forma de extender ActionController. He visto this post por DHH y this question aquí en SO, pero mi pregunta es más acerca de cómo llamar correctamente el código dentro del ActionController.Motor Rails 3.0 - Ejecutar código en ActionController

Por ejemplo, tengo que llamar al siguiente dentro del controlador de mi motor:

class ApplicationController < ActionController::Base 
    helper :all 

    before_filter :require_one_user 
    after_filter :store_location 

    private 
    def require_one_user 
     # Code goes here 
    end 

    def store_location 
     # Code goes here 
    end 
end 

sé cómo incluir adecuadamente mis dos funciones privadas, pero no puedo encontrar una manera de conseguir que se llama correctamente helper, before_filter y after_filter.

Agradecería mucho algunos enlaces o una forma de hacer que esto funcione. He intentado nombrar mi controlador como algo distinto de ApplicationController y tener el real ApplicationController ampliarlo, pero eso tampoco parece funcionar. Realmente estoy dispuesto a cualquier solución que haga que la vida del usuario del motor sea lo más fácil posible. Idealmente, no tendrían que extender mi clase, pero tendrían toda la funcionalidad integrada en su propia ApplicationController.

Respuesta

10

Es posible que también desee buscar en los inicializadores dentro de la subclase del motor, por lo que no tiene que incluir ayudantes de visualización dentro de su clase de controlador. Y esto le dará control sobre el orden de carga de estos módulos.

Aquí es lo que he estado usando:

 

module MyEngine 
    class Engine < Rails::Engine 
    initializer 'my_engine.helper' do |app| 
     ActionView::Base.send :include, MyEngineHelper 
    end 

    initializer 'my_engine.controller' do |app| 
     ActiveSupport.on_load(:action_controller) do 
     include MyEngineActionControllerExtension 
     end 
    end 
    end 
end 
 

Además, otra opción para la extensión del controlador de acción es el uso de un módulo de mixin. Esto le permitirá utilizar el before_filter, after_filter, etc ..

 

module MyEngineActionControllerExtension 
    def self.included(base) 
    base.send(:include, InstanceMethods) 
    base.before_filter :my_method_1 
    base.after_filter :my_method_2 
    end 

    module InstanceMethods 
    #........... 
    end 
end 
 

Otra cosa ... si crea los carriles predeterminados directorios en el nivel superior de la gema, que no tienen que preocuparse de que requiere los ayudantes o controladores. Su subclase del motor tiene acceso a ellos. Así agrego mi controlador de aplicaciones y extensiones de aplicación de ayuda aquí:

 
/myengine/app/helpers/myengine_application_helper_extension.rb 
/myengine/app/controllers/my_engine_action_controller_extension.rb 

me gusta esta configuración, ya que tiene una apariencia similar a la application_controller y application_helper en su aplicación rieles.De nuevo, esto es solo una preferencia personal, pero trato de mantener todo lo que esté directamente relacionado con los rieles, como controladores, helpers y modelos dentro de/my_engine/app y todo lo que esté relacionado con el plugin en general en/my_engine/lib

Echa un vistazo a este tutorial de José Valim para obtener más información sobre los inicializadores: https://gist.github.com/e139fa787aa882c0aa9c (engine_name está en desuso ahora, pero la mayoría de este documento parece actualizado)

+0

+1 y aceptado: ¡gracias por este impresionante informe! Aprecio que se tome el tiempo aunque ya lo "respondí" yo mismo. Es agradable ver una solución más elegante. Ah, y bienvenidos a Stack Overflow :-) –

3

Entonces, finalmente descubrí la solución y espero que ayude a alguien más.

Necesita crear un archivo en su directorio lib porque en realidad va a extender la clase. Hice myplugin/lib/extensions/action_controller_base.rb.

Luego, en el interior de su archivo myplugin/lib/myplugin.rb, haga lo siguiente:

require 'extensions/action_controller_base.rb' 

Dentro de myplugin/lib/extensions/action_controller_base.rb colocamos los siguientes:

require 'action_controller' # Make sure ActionController::Base is defined 

ActionController::Base.class_eval { 
    private 
    def my_method_1 
     # Code Goes Here 
    end 

    def my_method_2 
     # Code Goes Here 
    end 
} 

ActionController::Base.instance_eval { 
    helper_method :my_method_1, :my_method_2 

    before_filter :my_method_1 
    after_filter :my_method_2 
} 

Si se necesita tener ayudantes de vista, crearlos en el myplugin/lib/helpers directorio (o cualquier cosa dentro de lib, el nombre "ayudantes" no importa) también y agregue lo siguiente a la parte inferior de myplugin/lib/extensions/action_controller_base.rb:

require 'helpers/helper_file_1' 
require 'helpers/helper_file_2' 

ActionView::Base.send :include, MyHelper1 
ActionView::Base.send :include, MyHelper2 
Cuestiones relacionadas