I have an app with user and events. Each user has several events. When a user wants to see a specific event he will get to this action:
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
If the event is not found for the user it means he played with the URL and the event he is trying to get does not belong to him. I want to either redirect him to the main page or just display the page with an error that the event is not found. If I try to run the code above this error fires:
AbstractController::DoubleRenderError in EventsController#show
What's the best way to fix this?
Put return after redirect
begin
@userEvents = current_user.event
@event = @userEvents.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to :controller => "main", :action => "index"
return
end
Calling redirect_to
doesn't return from your action method which is why moving on to the respond_to
block causes the DoubleRenderError
. One way to fix that is with:
redirect_to :controller => "main", :action => "index" and return
However, a better solution might be to either rescue from this exception declaratively or just let it propagate to the client. The former look like this:
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
If you just let the exception fester the user will see the public/404.html
page in production mode.
In application controller, please write:
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
Create a page 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 %>
and in en.yml
en:
errors:
"404":
description: "The page you are looking for does not exist!"
heading: "Record not found"
subheading: ""
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With