I have stumbled upon a situation where my application looks for an id that does not exist in the database. An exception is thrown. Of course, this is a pretty standard situation
You must use rescue_from
for this task. See example in the Action Controller Overview Guide
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
private
def record_not_found
redirect_to action: :index
end
end
Rails has a built-in rescue_from class method:
class CustomersController < ApplicationController
rescue_from ActiveRecord::RecordNotFound, with: :index
...
end
In certain cases, I would recommend that you use Model.find_by_id(id)
as opposed to Model.find(id)
. Instead of throwing an exception, .find_by_id
returns nil
. if the record could not be found.
Just make sure to check for nils to avoid NoMethodError
!
P.S. For what it's worth, Model.find_by_id(id)
is functionally equivalent to Model.where(id: id)
, which would allow you to build out some additional relations if you want.
If you're talking about doing this within a single controller (as opposed to doing this globally in every controller) then here are a couple options:
You can use a before_filter to setup your resource:
class CustomerController < ApplicationController
before_filter :get_customer, :only => [ :show, :update, :delete ]
def show
end
private
def get_customer
@customer = ActiveRecord.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to :action => :index
end
end
Or you might use a method instead. I've been moving in this direction rather than using instance variables inside views, and it would also help you solve your problem:
class CustomerController < ApplicationController
def show
# Uses customer instead of @customer
end
private
def customer
@customer ||= Customer.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to :action => :index
end
helper_method :customer
end