5

Ich aktualisiere mein Rails-Plugin zu einer Engine, die mit der neuesten 3.0RC1-Version funktioniert, und ich habe ein wenig Mühe herauszufinden, die beste (und korrekteste) Art zu erweitern ActionController. Ich habe this post von DHH und this question hier auf SO gesehen, aber meine Frage ist mehr darüber, wie man richtig Code innerhalb der ActionController aufrufen.Rails 3.0 Engine - Ausführen von Code in ActionController

Zum Beispiel muß ich in der Steuerung meines Motors folgende nennen:

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 

Ich weiß, wie richtig meine zwei privaten Funktionen enthalten, aber ich kann nicht einen Weg, um es richtig zu nennen finden helper, before_filter und after_filter.

Ich würde sehr dankbar einige Links oder eine Möglichkeit, um dies zu arbeiten. Ich habe versucht, meinen Controller etwas anderes als ApplicationController zu nennen und die echte ApplicationController erweitern es, aber das scheint auch nicht zu funktionieren. Ich bin wirklich bereit für jede Lösung, die das Leben des Motorbenutzers so einfach wie möglich macht. Idealerweise müssten sie meine Klasse nicht erweitern, aber sie würden alle Funktionen in ihre eigene eingebaut haben.

Antwort

10

Sie können auch in die Initialisierer in Ihrer Engine-Unterklasse schauen, so dass Sie keine View-Helfer in Ihre Controller-Klasse aufnehmen müssen. Und das gibt Ihnen Kontrolle über die Ladereihenfolge dieser Module. Hier

ist das, was ich unter Verwendung worden:

 

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 
 

Auch eine weitere Option für die Aktion Controller-Erweiterung wird ein mixin Modul. So können Sie die before_filter verwenden, 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 
 

Eine andere Sache ... wenn Sie die Standard-Schienen-Verzeichnisse auf der obersten Ebene Ihrer Juwel erstellen, müssen Sie sich keine Sorgen darüber erfordern die Helfer oder Controller. Ihre Engine-Unterklasse hat Zugriff auf sie. So füge ich meine Anwendung Controller und Helfer Anwendungserweiterungen hier:

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

ich dieses Setup mag, weil es auf die application_controller und application_helper in Ihrer Rails-Anwendung ähnlich sieht.Auch dies ist nur persönliche Vorliebe, aber ich versuche, alles, was direkt Schienen betrifft, wie Controller, Helfer und Modelle in/my_engine/app und alles, was mit dem Plugin im Allgemeinen in/my_engine/lib

In diesem Tutorial von Jose Valim finden Sie weitere Informationen zu Initializern: https://gist.github.com/e139fa787aa882c0aa9c (Engine-Name ist jetzt veraltet, aber das meiste scheint aktuell zu sein)

+0

+1 und Accepted - Danke für diesen tollen Bericht! Ich schätze es, dass du dir die Zeit genommen hast, obwohl ich sie bereits selbst "beantwortet" habe. Es ist schön, eine elegantere Lösung zu sehen. Oh, und willkommen bei Stack Overflow :-) –

3

Also, ich habe endlich die Lösung gefunden und ich hoffe, es hilft jemand anderem.

Sie müssen eine Datei in Ihrem lib-Verzeichnis erstellen, da Sie die Klasse tatsächlich erweitern werden. Ich habe myplugin/lib/extensions/action_controller_base.rb getan.

Dann innerhalb Ihrer myplugin/lib/myplugin.rb Datei, gehen Sie wie folgt vor:

require 'extensions/action_controller_base.rb' 

Innerhalb von myplugin/lib/extensions/action_controller_base.rb setzen Sie die folgenden:

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 
} 

Wenn Sie View Helfer haben, schaffen sie in der myplugin/lib/helpers Verzeichnis (oder irgendetwas innerhalb von lib, der Name "Helfer" spielt keine Rolle) und füge folgendes hinzu: 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