2010-12-07 5 views
9

Noob Scoping Frage, ich stelle mir vor. : \Rails: Wie greife ich auf eine Methode in meinem Application Controller zu?

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    @locations = get_locations 

    def get_locations 
    Location.where(:active => true).order('name').all 
    end 

end 

Fehler:

undefined local variable or method `get_locations' for ApplicationController:Class 

Zwei Fragen: 1) Was mit dem Fehler ist? Rufe ich die Methode falsch an? 2) Wie greife ich von einem untergeordneten Controller auf diese Methode zu?

Antwort

9

Sie rufen innerhalb des Klassenbereichs get_locations auf, aber die Methode ist eine Instanzmethode, keine Klassenmethode. Wenn Sie zum Beispiel def self.get_locations verwendet haben, dann würden Sie eine Klassenmethode bereitstellen, von denen Sie eine innerhalb des Klassenbereichs verwenden können (nachdem Sie es definiert haben, nicht vorher, wie Sie es tun).

Das Problem hier ist die Logik, für was ist diese Methode? Was wollen Sie für @locations verwenden? Wenn Sie in Ihre Anwendungsansicht wechseln möchten, sollten Sie diese Methode in das Modul ApplicationHelper einfügen und von der entsprechenden Aktion aus aufrufen. Wenn Sie es in einer anderen Ansicht auf einen anderen Controller möchten und Sie möchten, dass @locations in Ihrem locations Methode verwenden, vielleicht könnte das Setup etwas wie folgt aussehen:

PagesController

class PagesController < ActionController::Base 
    def locations 
    @locations = Location.where(:active => true).order('name').all 
    end 
end 

Standorte .html.erb

<% @locations.each do |location| %> 
    <%= # do something with 'location' %> 
<% end %> 

Wenn Sie das Innere Ihres verwenden möchten application.html.erb Sie können si mplify es ziemlich einige ..

Application

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    def locations 
    Location.where(:active => true).order('name').all 
    end 
end 

application.html.erb

<% locations.each do |location| %> 
    <%= # do something with location %> 
<% end %> 

Die Antwort läuft darauf hinaus, Logik nach unten, und wirklich, genau herauszufinden, was Sie suchen, mehr Details wäre wahrscheinlich erforderlich.

+0

Ich brauche @locations für mein Anwendungslayout, aber auch für einen anderen Controller. Der beste Ort, um dies zu setzen? – jmccartie

+0

Wenn Sie in Ihrem Anwendungslayout darauf zugreifen müssen, ist Ihr Anwendungscontroller wahrscheinlich der beste Ort, um ihn zu verwenden, da er auf Ihren Controllern verfügbar ist. Lassen Sie Ihren Controller 'before_filter' auf Ihrer Methode' get_locations' aufrufen, um die Instanzvariable '@ locations' zu füllen –

1

Ich stelle mir vor, dass diese Linie:

@locations = get_locations 

... versucht, die Klassenstufe Methode get_locations und nicht die Instanz-Methode zuzugreifen.

Der Hinweis hier ist, dass die Fehlermeldung zeigt, dass es nicht in der Klasse selbst finden kann (ApplicationController: Class) und nicht eine Instanz dieser Klasse. Das bedeutet, dass Sie sich im Klassenbereich befinden und nicht im Instanzbereich.

Dies würde das Problem beheben:

def self.get_locations 
    Location.where(:active => true).order('name').all 
    end 
+0

@@ Stellen nicht ist, was Sie wollen. Es ist eine wahre Klassenvariable, die in Ruby zwischen allen Instanzen der Klasse * einschließlich Unterklassen * geteilt wird und einige wirklich seltsame Konsequenzen haben kann. – karmajunkie

+0

Woops, notiert (und bearbeitet). Vielen Dank. – markquezada

3

Sie es aus dem Klassenbereich aufrufen, nicht von einer Instanz Umfang. wahrscheinlicher, was Sie wollen, ist die folgende:

class ApplicationController < ActionController::Base 
    protect_from_forgery 
    before_filter :setup_locations 


    private 
    def setup_locations 
    @locations = Location.where(:active => true).order('name').all 
    end 

end 

um Ihre ursprünglichen Beispiel Arbeit zu machen, Sie #get_locations auf sich selbst definiert machen bräuchten (die bei der Bestimmung der Klasse Punkte), etwa so:

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    @locations = get_locations 

    def self.get_locations 
    Location.where(:active => true).order('name').all 
    end 

end 

Das Problem mit diesem Code ist, dass @locations nur von der Klassenebene als Klasseninstanzvariable verfügbar ist, die mit einer statischen Variable in den meisten anderen Sprachen vergleichbar ist und die wahrscheinlich nicht das ist, was Sie wollen.

+0

Seltsamerweise erzeugt das zweite Beispiel genau den gleichen Fehler. Das erste Beispiel scheint zu funktionieren - aber das würde meine Fähigkeit einschränken, diese Methode von einem anderen Controller aus aufzurufen, richtig? (Danke für Ihre Hilfe!) – jmccartie

+0

Es wäre, aber wenn Sie die gleiche Methode von anderen Controllern verwenden möchten, legen Sie es in Ihrem Anwendungscontroller, der sowieso die Basisklasse für Ihre Controller sein sollte (ApplicationController-Unterklassen ActionController :: Base typischerweise) – karmajunkie

1

Auch die Frage ziemlich alt ist, können Sie auch telefonisch überall nur Ihre Controller-Aktion nennen:

an Sicherheit grenzender Wahrscheinlichkeit
ApplicationController.new.get_locations 
Verwandte Themen