Hola , buenas
Esta duda es más de ruby que de RoR, pero espero que me podais ayudar de
todos modos.
Me gustaria saber cual es la mejor manera de detener la ejecucion de una
aplicacion ruby en un punto concreto.
Ejemplo:
En el ApplicationController tengo un before_filter para controlar que
tras un tiempo de inactividad mate la sesion. En el metodo de este
filtro lo que hago tras hacer las comprobaciones, resetear la sesion y
redirigir a una accion donde explico al usuario lo que ha pasado.
El problema que tengo es que si tras salir del metodo y ser redirigido
hay alguna otra accion por debajo que redirija, pues me sale un
bonito DoubleRenderError.
Por ejemplo si en el momento en el que se le expira la sesion al usuario
trataba de acceder a un sitio donde se supone que no tiene permiso, pues
me salta el filtro del ApplicationController y despues el de el
controlador que va por debajo que le trata de redirigir.
Y no es solo para este caso concreto, me he visto con esta
necesidad en otras ocasiones que ahora no recuerdo, jeje.
Bueno, espero vuestros consejos.
Un Saludo, Alfredo.
On Nov 15, 2007 9:21 AM, Alfredo Garcia lopez
[email protected] wrote:
En el ApplicationController tengo un before_filter para controlar que
tras un tiempo de inactividad mate la sesion. En el metodo de este
filtro lo que hago tras hacer las comprobaciones, resetear la sesion y
redirigir a una accion donde explico al usuario lo que ha pasado.
¿Qué pasa si el filtro devuelve false?
On Nov 15, 2007, at 1:21 PM, Alfredo Garcia lopez wrote:
En el ApplicationController tengo un before_filter para controlar que
tras un tiempo de inactividad mate la sesion. En el metodo de este
filtro lo que hago tras hacer las comprobaciones, resetear la sesion y
redirigir a una accion donde explico al usuario lo que ha pasado.
El problema que tengo es que si tras salir del metodo y ser redirigido
hay alguna otra accion por debajo que redirija, pues me sale un
bonito DoubleRenderError.
En Rails pre-2.0 un filtro debe devolver el booleano false para
interrumpir el flujo de la peticion. Ademas ha de ser exactamente
false, no es suficiente que sea un valor booleanamente falso.
En 2.0 un render o redirect bastan.
– fxn
On Nov 16, 2007, at 1:34 PM, Alfredo Garcia lopez wrote:
Todos los ejemplos reales que se me ocurren se pueden implementar
mediante filtros, pero es solo por saber si es posible.
Yo veo ahi al menos dos aproximaciones.
Si esa logica es muy local entonces la basaria en valores de retorno
de los metodos anidados. Eso es lo que haces cuando escojes que hacer
en funcion de lo que devuelve model.save.
Si es mas generico y necesitas tener puntos de salida globales y
faciles, entonces en Rails 2.0 tienes rescue_from
class ApplicationController < …
rescue_from MyException, :with => :handler
end
No importa lo lejos que estes en la cadena de llamadas, si lanzas
MyException iras a parar a handler.
En pre-2.0 tienes un solo handler global rescue_action and friends,
donde harias un case por la excepcion para entendernos.
– fxn
Xavier N. wrote:
On Nov 16, 2007, at 1:34 PM, Alfredo Garcia lopez wrote:
Todos los ejemplos reales que se me ocurren se pueden implementar
mediante filtros, pero es solo por saber si es posible.
Yo veo ahi al menos dos aproximaciones.
Si esa logica es muy local entonces la basaria en valores de retorno
de los metodos anidados. Eso es lo que haces cuando escojes que hacer
en funcion de lo que devuelve model.save.
Si es mas generico y necesitas tener puntos de salida globales y
faciles, entonces en Rails 2.0 tienes rescue_from
class ApplicationController < …
rescue_from MyException, :with => :handler
end
No importa lo lejos que estes en la cadena de llamadas, si lanzas
MyException iras a parar a handler.
En pre-2.0 tienes un solo handler global rescue_action and friends,
donde harias un case por la excepcion para entendernos.
– fxn
Ok, gracias de nuevo Xavier.
Todo aclarado.
Todavia ando con pre-2.0.
Cuando tenga tiempo me meto con la nueva version.
un saludo, Alfredo.
Xavier N. wrote:
On Nov 16, 2007, at 1:34 PM, Alfredo Garcia lopez wrote:
Todos los ejemplos reales que se me ocurren se pueden implementar
mediante filtros, pero es solo por saber si es posible.
Yo veo ahi al menos dos aproximaciones.
Si esa logica es muy local entonces la basaria en valores de retorno
de los metodos anidados. Eso es lo que haces cuando escojes que hacer
en funcion de lo que devuelve model.save.
Si es mas generico y necesitas tener puntos de salida globales y
faciles, entonces en Rails 2.0 tienes rescue_from
class ApplicationController < …
rescue_from MyException, :with => :handler
end
No importa lo lejos que estes en la cadena de llamadas, si lanzas
MyException iras a parar a handler.
En pre-2.0 tienes un solo handler global rescue_action and friends,
donde harias un case por la excepcion para entendernos.
– fxn
Espera, creo que me he precipitado al responder.
Lo de basarlo en valores de retorn lo he entendido, pero en lo de lanzar
excepciones tanto en pre-2.0 tanto como en 2.0 con rescue_from tengo una
duda.
def metodo1
begin
metodo2
rescue Exception=>e
end
end
def metodo2
if condicion
…
else
raise MiExcepcion
end
end
private
def rescue_action(exception)
case exception
when MiExcepcion
redirect_to(“mi_excepcion”)
end
end
¿Que pasaria aqui?
Gracias,Alfredo.
Xavier N. wrote:
On Nov 15, 2007, at 1:21 PM, Alfredo Garcia lopez wrote:
En el ApplicationController tengo un before_filter para controlar que
tras un tiempo de inactividad mate la sesion. En el metodo de este
filtro lo que hago tras hacer las comprobaciones, resetear la sesion y
redirigir a una accion donde explico al usuario lo que ha pasado.
El problema que tengo es que si tras salir del metodo y ser redirigido
hay alguna otra accion por debajo que redirija, pues me sale un
bonito DoubleRenderError.
En Rails pre-2.0 un filtro debe devolver el booleano false para
interrumpir el flujo de la peticion. Ademas ha de ser exactamente
false, no es suficiente que sea un valor booleanamente falso.
En 2.0 un render o redirect bastan.
– fxn
Ok, muchas gracias a los 2.
Por lo que me habeis comentado si un filtro devuelve explicitamente
false, detiene todo el flujo que esta por debajo.
¿Hay manera de hacerlo en metodos normales que no sean filtros?.
Ej:
En un metodo llamo a otro metodo, en este otro metodo tengo claro que si
se da una condicion quiero detener el flujo de la aplicacion.
¿Es posible?
Todos los ejemplos reales que se me ocurren se pueden implementar
mediante filtros, pero es solo por saber si es posible.
Muchas gracias, Alfredo.
On Nov 16, 2007, at 2:23 PM, Alfredo Garcia lopez wrote:
rescue Exception=>e
end
private
def rescue_action(exception)
case exception
when MiExcepcion
redirect_to(“mi_excepcion”)
end
end
¿Que pasaria aqui?
Saltaria el handler.
Mira te pongo un caso practico de uso de excepciones con rescue_from:
En ASPgems estamos haciendo un web service RESTful. En REST cuando
algo va mal se envia un 4xx o 5xx al cliente. Bien, pues tenemos una
jerarquia de excepciones para ciertos problemas y un handler global
para la raiz de la jerarquia que hace de catchall[*]:
rescue_from BookingGatewayError::Base, :with => lambda { |exception|
render :xml => exception, :status => exception.status
}
Nuestro web service tiene las responsabilidades definidas de tal
manera que varios puntos de la aplicacion pueden decidir que algo fue
mal, saben por que, y saben que hay que interrumpir y reportar tal
error. Bien, para ello lanzan la excepcion mas especifica de la
jerarquia y las acciones la dejan pasar para que suba hasta el
rescue_from. Nadie hace un rescue intermedio de esas.
BTW, una tercera opcion es lanzar excepciones para ser tratadas
localmente claro (la version model.save! de model.save), eso seria
analogo a la primera. La aproximacion rescue_from en cuanto a este
thread tiene sentido cuando esta bien saltar directamente al handler
en el control de flujo. Tiene otras aplicaciones tambien.
– fxn
[*] En la prerelease no se soportaba herencia de excepciones en
rescue_from, en la RC1 si.