2010-12-07 7 views
9

Noob tema de alcance, me imagino. : \rieles: ¿cómo accedo a un método en mi controlador de aplicación?

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    @locations = get_locations 

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

end 

error:

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

Dos preguntas: 1) ¿Cuál es el error? ¿Estoy llamando al método incorrectamente? 2) ¿Cómo accedo a este método desde un controlador sub-clasificado?

Respuesta

9

Llama al get_locations dentro del alcance de clase, pero el método es un método de instancia, no un método de clase. Si, por ejemplo, usaste def self.get_locations, entonces proporcionarías un método de clase, uno de los cuales puedes usar dentro del alcance de la clase (después de haberlo definido, no antes como lo haces).

El problema aquí es la lógica, ¿para qué sirve este método? ¿Para qué quieres usar @locations? Si va a entrar en la vista de la aplicación, debe poner este método en el módulo ApplicationHelper y llamarlo desde dentro de la acción relevante. Si desea que en otra vista en otro controlador y desea utilizar @locations dentro de su método locations, tal vez su configuración podría ser algo como esto:

PagesController

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

ubicaciones .html.erb

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

Si desea utilizar este interior de su application.html.erb puede šī lo simplifico bastante ...

ApplicationController

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 %> 

La respuesta se reduce a la lógica, y para realmente saber exactamente lo que está buscando, más detalles probablemente sería requerido.

+0

Necesito @ ubicaciones disponibles para el diseño de mi aplicación, pero también para otro controlador. El mejor lugar para poner esto? – jmccartie

+0

Si necesita acceder a él en el diseño de su aplicación, entonces su controlador de aplicación es probablemente el mejor lugar para colocarlo, ya que estará disponible para todos sus controladores. Haga que su controlador llame a 'before_filter' en su método' get_locations' para rellenar la variable de instancia '@ locations' –

1

me imagino que esta línea:

@locations = get_locations 

... está tratando de acceder al método de nivel de clase get_locations y no el método de instancia.

La clave aquí es que el mensaje de error muestra que no puede encontrarlo en el clase (ApplicationController: Class) y no es una instancia de esa clase. Eso significa que estás en el alcance de la clase, no en el alcance de la instancia.

Esto solucionarlo:

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

@@ lugares es casi seguro que no lo desea. Es una variable de clase verdadera, que en Ruby se comparte entre todas las instancias de la clase, * incluidas las subclases * y puede tener algunas consecuencias realmente extrañas. – karmajunkie

+0

Woops, anotado (y editado). Gracias. – markquezada

3

que está llamando desde el ámbito de la clase, no de un alcance ejemplo. más probable que lo que desea es la siguiente:

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 

Para hacer su trabajo original ejemplo, que había necesidad de hacer #get_locations definidos en sí (que apunta a la clase en la definición), así:

class ApplicationController < ActionController::Base 
    protect_from_forgery 

    @locations = get_locations 

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

end 

El problema con ese código es que @locations solo estará disponible desde el nivel de clase como una variable de instancia de clase, que es comparable a una variable estática en la mayoría de los otros idiomas y que probablemente no es lo que desea.

+0

Por extraño que parezca, el segundo ejemplo genera exactamente el mismo error. El primer ejemplo parece funcionar bien, pero esto limitaría mi capacidad para llamar a este método desde otro controlador, ¿verdad? (¡gracias por su ayuda!) – jmccartie

+0

Lo haría, pero si desea utilizar el mismo método de otros controladores, póngalo en su controlador de aplicación, que debería ser la clase base para sus controladores de todos modos (subclases ApplicationController ActionController :: Base normalmente) – karmajunkie

1

Incluso la cuestión es bastante antiguo, también puede llamar a su acción del controlador en cualquier lugar con sólo llamar:

ApplicationController.new.get_locations 
Cuestiones relacionadas