Rails 3.0 Motore - eseguire codice in ActionController
-
28-09-2019 - |
Domanda
Sto aggiornando il mio Rails plugin per essere un motore che funziona con l'ultima versione 3.0RC1 e sto avendo un po 'di difficoltà a capire il migliore (e più corretto) modo per estendere ActionController
. Ho visto questo post da DHH e questa domanda qui su SO, ma la mia domanda è di più su come chiamare correttamente il codice all'interno del ActionController
.
Per esempio, ho bisogno di chiamare il seguente all'interno del controller del mio motore:
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
So come includere correttamente le mie due funzioni private, ma non riesco a trovare un modo per farlo chiamare correttamente helper
, before_filter
e after_filter
.
Io apprezzo molto alcuni link o un modo per fare questo lavoro. Ho provato nominare il mio controller qualcosa di diverso da ApplicationController
e avere la vera ApplicationController
estenderla, ma che non sembra funzionare. Sono davvero per qualsiasi soluzione che rende la vita del utente del motore più semplice possibile. Idealmente, essi non avrebbero dovuto estendere la mia classe, ma avevano avere tutte le funzionalità integrate nel proprio ApplicationController
.
Soluzione
Si può anche voler guardare negli inizializzatori all'interno della vostra sottoclasse del motore, in modo da non è necessario includere vista aiutanti all'interno della vostra classe controller. E questo vi darà di controllare l'ordine di caricamento di questi moduli.
Ecco quello che ho utilizzato:
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
Inoltre, un'altra opzione per l'estensione regolatore azione sta utilizzando un modulo mixin. Questo vi permetterà di utilizzare il 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
Un altra cosa ... se si crea il default rotaie directory al livello più alto del vostro gioiello, non si deve preoccuparsi di richiedere gli aiutanti o controller. Il tuo sottoclasse motore ha accesso ad essi. Quindi aggiungo il mio controller delle applicazioni e le estensioni applicazione di supporto qui:
/myengine/app/helpers/myengine_application_helper_extension.rb /myengine/app/controllers/my_engine_action_controller_extension.rb
Mi piace questa messa a punto perché sembra simile al application_controller e application_helper nella vostra applicazione Rails. Ancora una volta, questa è la preferenza solo personale, ma cercare di mantenere tutto ciò che è direttamente rotaie correlati, come controllori, aiutanti e modelli all'interno / my_engine / app e tutto ciò che è legato al plugin in all'interno generale / my_engine / lib
Guarda questo tutorial da José Valim per più informazioni inizializzatori: https://gist.github.com/e139fa787aa882c0aa9c (ENGINE_NAME è deprecato ora, ma la maggior parte di questo documento sembra up-to-date)
Altri suggerimenti
Così, ho finalmente capito la soluzione e spero che aiuta a qualcun altro.
È necessario creare un file nella directory lib, perché in realtà si sta andando ad estendere la classe. Ho fatto myplugin/lib/extensions/action_controller_base.rb
.
Poi, all'interno del file myplugin/lib/myplugin.rb
, procedere come segue:
require 'extensions/action_controller_base.rb'
All'interno della myplugin/lib/extensions/action_controller_base.rb
mettere il seguente:
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
}
Se avete bisogno di avere vista aiutanti, li creare nella directory myplugin/lib/helpers
(o nulla all'interno dei lib, il nome "aiutanti" non importa) anche e aggiungere il seguente al fondo della 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