ruby-on-rails - rails - ruby print in console
Rieles: establezca una variable de instancia comĂșn en varias acciones del controlador (3)
En primer lugar, no desea intentar insertar el código "entre" una acción del controlador y una representación de plantilla. ¿Por qué? Porque desea que la acción del controlador tenga la libertad de elegir qué tipo de respuesta dar. Podría devolver XML, JSON, solo encabezados, una redirección, nada, etc. Es por eso que después de que se ejecutan los filtros después de que se haya procesado la respuesta.
En segundo lugar, no quieres parches Fixnum
. Quiero decir, tal vez sí, pero no lo hago. No a menudo al menos, y no a menos que obtenga algunos beneficios semánticos totalmente perversos, como ser capaz de decir 3.blind_mice
. El parche parcheado para un caso de uso aleatorio como este parece ser un dolor de cabeza de mantenimiento en el futuro.
Usted menciona refactorizar todo el código específico de la caja de los controladores en un filtro anterior y ejecutarlos secuencialmente. Lo que me @foo
a la mente ... @foo
es el mismo en todos los casos? Si ese es el caso, entonces uno antes del filtro funcionaría bien:
before_filter :do_common_stuff
def do_common_stuff
@foo = common_foo
@bar = do_something_with @foo
end
Ese es un enfoque totalmente legítimo. Pero si @foo cambia de controlador a controlador ... bueno, tienes algunas opciones más.
Puede separar los filtros anteriores en dos mitades y personalizar uno por controlador.
# application_controller:
before_filter :get_foo, :do_something_common
def do_something_common
@bar = do_something_with @foo
end
# baz_controller:
def get_foo
@foo = pull_from_mouth
end
#baf_controller:
def get_foo
@foo = pull_from_ear
end
Pero ya sabes, si es un caso simple que no necesita acceso a la base de datos o acceso a la red o algo así ... que tu caso no ... no se suicide. Y no te preocupes. Tirarlo en un ayudante. Para eso están, para ayudar. Básicamente, simplemente está reorganizando algunos datos de vista en una forma un poco más fácil de usar de todos modos. Un ayudante es mi voto. Y simplemente puedes nombrarlo next_url
. :)
¿Cómo debería uno tener varias acciones de controlador diferentes establecer una variable de instancia común para uso en plantillas pero después de que se ejecuta la acción .
En otras palabras, quiero que esto funcione en mi controlador de aplicaciones.
class ApplicationController < ActionController::Base
after_filter :set_something_common
def set_something_common
# All controllers'' actions have queried the DB and set @foo for me...
@bar = some_calculation_on(@foo)
# ... and all templates expect @bar to bet set.
end
end
Esto no funciona porque after_filter
ejecuta después de la representación. Multa. Pero, ¿cuál es el patrón correcto?
Nuevamente, es importante que set_something_common
ejecute después de la acción porque esas acciones hacen cosas específicas de cada caso; pero todos ellos establecen @foo
.
Ninguna de mis ideas parece ideal:
- Llame a
set_something_common()
hacia la parte inferior de cada acción que lo necesite. Refactorice el código específico de caso de todos los controladores en
case_specific_code()
y obligue a que se ejecuten en orden:before_filter :case_specific_code, :set_something_common
Subclase
application_controller
y redefine el método deindex
.
¿Alguna idea? Gracias.
Edit: la respuesta de Matthew me impulsó a aclarar:
El índice de varios controladores () hace paginación, y cada uno toma los parámetros @offset
y @limit
(a través de un before_filter
global) para ver los segmentos de datos. Genial. Ahora quiero un método común para calcular una URL RESTful para el enlace "siguiente porción". Me animaron a ver que url_for()
genera una URL que regresa al mismo recurso, así que intenté:
def set_something_common # really called set_next_url, truth be told
@next_url = url_for(:offset => @offset + @limit, :limit => @limit)
end
Trataré de parchear el parche Fixnum, así que puedo hacer algo como @offset.next_url_for(self, @limit)
desde la plantilla, pero no estoy seguro de si funcionará. Ahora que lo pienso, si voy a modificar las plantillas, entonces también puedo configurar un asistente de aplicación. Todavía no estoy seguro de cuál es la mejor solución.
Actualización: La respuesta aceptada es "usar un ayudante".
Gracias por las actualizaciones de todos. Aprendí mi lección de que los ayudantes, como las variables globales, están ahí por una razón y no deben ser evitados cuando son claramente beneficiosos y sucintos.
Tendría un método en @foo
que devuelve una barra, de esa manera puedes usar @foo.bar
en tus vistas.
<% @bar = @foo.bar %>
# si realmente no quieres cambiar tus puntos de vista, pero no escuchaste esto de mí :)
Use <%= do_some_calculations(@foo) %>
dentro de sus plantillas. Ese es el camino recto.