2012-10-01 20 views
14

Tengo una aplicación con usuarios y eventos. Cada usuario tiene varios eventos. Cuando un usuario quiere ver un evento específico que va a llegar a esta acción:cómo manejar ActiveRecord :: RecordNotFound en el controlador de rieles?

def show 
    begin 
    @userEvents = current_user.event 
    @event = @userEvents.find(params[:id]) 
    rescue ActiveRecord::RecordNotFound 
    redirect_to :controller => "main", :action => "index" 
    end 

    respond_to do |format| 
    format.html # show.html.erb 
    format.json { render json: @event } 
    end 
end 

Si no se encuentra el caso de que el usuario quiere decir que jugó con el URL y el evento que está tratando de conseguir no pertenece a él. Quiero redirigirlo a la página principal o simplemente mostrar la página con un error de que no se encuentra el evento. Si trato de ejecutar el código anterior esta incendios de error:

AbstractController::DoubleRenderError in EventsController#show 

¿Cuál es la mejor manera de solucionar este problema?

Respuesta

20

Put regresar después de redirigir

begin 
@userEvents = current_user.event 
@event = @userEvents.find(params[:id]) 
rescue ActiveRecord::RecordNotFound 
redirect_to :controller => "main", :action => "index" 
return 
end 
+0

oh dios gracias .... enviar el mensaje desde el futuro =) –

14

Calling redirect_to no vuelve de su método de acción que es la razón de pasar al bloque respond_to hace que el DoubleRenderError. Una forma de solucionar eso es con:

redirect_to :controller => "main", :action => "index" and return 

Sin embargo, una mejor solución podría ser la de cualquiera rescue from esta excepción de forma declarativa o simplemente dejar que se propague hacia el cliente. El primero tener este aspecto:

class YourController < ActionController::Base 

    rescue_from ActiveRecord::RecordNotFound, with: :dude_wheres_my_record 

    def show 
    # your original code without the begin and rescue 
    end 

    def dude_where_my_record 
    # special handling here 
    end 
end 

Si usted acaba de dejar la excepción fester el usuario verá la página public/404.html en el modo de producción.

+0

no acallar entender su solución ... ¿por qué debería suceder que el rescate cada vez que en el controlador? .. lo necesito sólo en el mostrar acción. pero gracias –

+0

El 'rescue_from' es simplemente una manera más agradable de lidiar con errores comunes a veces, lo que le permite separar preocupaciones en su código. Por supuesto que no siempre es mejor, de ahí las otras dos opciones :-) – noodl

+0

Gracias ... a mí también me funcionó =) –

5

En controlador de aplicación, puede escribir:

rescue_from (ActiveRecord::RecordNotFound) { |exception| handle_exception(exception, 404) } 

    protected 

    def handle_exception(ex, status) 
     render_error(ex, status) 
     logger.error ex 
    end 

    def render_error(ex, status) 
     @status_code = status 
     respond_to do |format| 
      format.html { render :template => "error", :status => status } 
      format.all { render :nothing => true, :status => status } 
     end 
    end 

crear una página error.html.erb

<div class="page-header"> 
    <h1> 
    <%= t "errors.#{@status_code}.heading" %> 
    <small><%= t "errors.#{@status_code}.subheading" %></small> 
    </h1> 
</div> 
<p><%= t "errors.#{@status_code}.description" %></p> 
<% if defined? root_path %> 
    <%= link_to t(:return_to_home), root_path %> 
<% end %> 

y en en.yml

en: 
    errors: 
    "404": 
     description: "The page you are looking for does not exist!" 
     heading: "Record not found" 
     subheading: "" 
+0

Nota rápida, error.htm.erb debe ir dentro de la raíz de la carpeta/views. –

Cuestiones relacionadas