Reputation: 917
What is the best way to handle the error then ID is not found? I have this code in my controller:
def show
@match = Match.find(params[:id])
end
I was thinking about something like this:
def show
if @match = Match.find(params[:id])
else
render 'error'
end
end
But I still get:
ActiveRecord::RecordNotFound in MatchesController#show
Couldn't findMatch with 'id'=2
Why?
What is the correct solution?
Upvotes: 15
Views: 12132
Reputation: 4716
There is two approaches missing:
One is to use a Null-Object (there I leave research up to you)
Te other one was mentioned, but can be placed more reusable and in a way more elegantly (but it is a bit hidden from you action code because it works on a somewhat higher level and hides stuff):
class MyScope::MatchController < ApplicationController
before_action :set_match, only: [:show]
def show
# will only render if params[:id] is there and resolves
# to a match that will then be available in @match.
end
private
def set_match
@match = Match.find_by(id: params[:id])
if [email protected]?
# Handle somehow, i.e. with a redirect
redirect_to :back, alert: t('.match_not_found')
end
end
end
Upvotes: 0
Reputation: 383
You can use find_by_id method it returns nil instead of throwing exception
Model.find_by_id
Upvotes: 1
Reputation: 160873
Rescue it in the base controller and leave your action code as simple as possible. You don't want to deal not found exception in every action, do you?
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :render_404
def render_404
render :template => "errors/error_404", :status => 404
end
end
Upvotes: 36
Reputation: 1402
By default the find
method raises an ActiveRecord::RecordNotFound
exception. The correct way of handling a not found record is:
def show
@match = Match.find(params[:id])
rescue ActiveRecord::RecordNotFound => e
render 'error'
end
However, if you prefer an if/else approach, you can use the find_by_id
method that will return nil:
def show
@match = Match.find_by_id(params[:id])
if @match.nil? # or unless @match
render 'error'
end
end
Upvotes: 7