2010-08-04 13 views
11

En mi controlador de controlador, tengo el uso Date.new para crear un objeto de fecha que se pasará en mi ActiveRecord.raise ActiveRecord :: RecordNotFound (o cualquier estado 404) para la fecha no válida

end_range = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i).end_of_day.to_formatted_s(:db) 

El problema con esto es que por encima de si un usuario ha intentado cambiar los parámetros de la URL de forma manual, como cuando se entra 40 parámetro para el día, el Date.new falla (como se esperaba). Sin embargo, prefiero no tener un error de 500 si un usuario escribió algo así, sino un error 404 (porque nunca podrá grabar un día con 40).

He intentado varias condicionales (if y unless declaraciones) a raise ActiveRecord::RecordNotFound si eso falla, pero devuelve el error 500 antes de ejecutar el condicional (y por lo tanto no devolver un 404).

¿Alguien sabe una mejor manera de manejar eso, o una forma de permitir que el Date.new falle con mayor gracia para que pueda ejecutarse la instrucción condicional?

Respuesta

28

En este caso es posible rescatar una excepción y elevar otra si desea volver a mapa excepciones que no se manejan en el tipo que son:

def show 
    begin 
    end_range = Date.new(...) 
    rescue ArgumentError 
    # Invalid date 
    raise ActiveRecord::RecordNotFound 
    end 
rescue ActiveRecord::RecordNotFound 
    render(:partial => 'not_found', :layout => 'application', :status => :not_found) 
end 

Podría ser más eficiente simplemente render y fallar de inmediato.

def show 
    begin 
    end_range = Date.new(...) 
    rescue ArgumentError 
    return render(:partial => 'date_not_found', :layout => 'application', :status => :not_found) 
    end 
end 

También puede hacer esto en un sentido más radical utilizando el método de ApplicationController rescue_from:

class ApplicationController < ActionController::Base 
    rescue_from 'ArgumentError do 
    render(:partial => 'exceptions/argument_error', :layout => 'application', :status => :not_found) 
    end 
end 
+0

Gracias, que funcionó. El segundo ejemplo funciona muy bien, eso es lo que estaba buscando, pero comencé a intentar a través de un NotFound de ActiveRecord solo para obtener algo distinto de 500. (Si alguien lee, esto, ActiveRecord está mal escrito en el primer ejemplo.) –

+0

Fixed el error tipográfico Me alegro de que funcionó para ti. – tadman

1

creo que tiene más sentido para rescatar a un error de fecha no válido con un mensaje útil. Este es un problema común cuando las personas seleccionan el 30 de febrero, por ejemplo. Preferiría enviarlos de vuelta al formulario en cuestión y decirles por qué se los devuelve. Un 404 sería incorrecto en la mayoría de los casos, ya que el error es una entrada de usuario no válida, no una URL inválida.

Además, si rescatas a todos ArgumentError s no recibirás notificaciones de otros errores relacionados con el código. Entonces, si no es un error de fecha, entonces estoy volviendo a generar el error. Desafortunadamente tenemos que cambiar el tipo de excepción para evitar un bucle.

He puesto esto en el application_controller:

rescue_from ArgumentError do |exception| 
    if exception.message == 'invalid date' 
    flash[:error] = exception.message 
    redirect_to request.referer ? :back : root_url 
    else 
    raise StandardError, exception.message, exception.backtrace 
    end 
end 
+1

esta respuesta es mejor, ¡más orientado a Rails! – caesarsol

+1

No se recomiendan los StandardErrors. Son simplemente demasiado básicos y no explican ningún contexto, solo el hecho de que se ha planteado alguna excepción. – maikovich

Cuestiones relacionadas