Rails 2: Model.find(1) gives ActiveRecord error when id 1 does not exist

大城市里の小女人 提交于 2019-12-17 06:12:10

问题


I am using Rails 2.3.5 and in that if I give Model.find(1) and if 1 is not in the database, it returns ActiveRecord error. Should it just be returning nil as in the case of Model.find_by_column('..')?


回答1:


This is the expected behavior. I think David explains this the best himself, so here is a quote from Ruby, S., Thomas, D. & Hansson, D.H., 2009. Agile Web Development with Rails, Third Edition Third Edition., Pragmatic Bookshelf (p.330).

When you use a finder driven by primary keys, you’re looking for a particular record. You expect it to exist. A call to Person.find(5) is based on our knowledge of the people table. We want the row with an id of 5. If this call is unsuccessful—if the record with the id of 5 has been destroyed—we’re in an exceptional situation. This mandates the raising of an exception, so Rails raises RecordNotFound.

On the other hand, finders that use criteria to search are looking for a match. So, Person.find(:first, :conditions=>"name=’Dave’") is the equivalent of telling the database (as a black box) “Give me the first person row that has the name Dave.” This exhibits a distinctly different approach to retrieval; we’re not certain up front that we’ll get a result. It’s entirely possible the result set may be empty. Thus, returning nil in the case of finders that search for one row and an empty array for finders that search for many rows is the natural, nonexceptional response.




回答2:


If you really don't want the exception, you can use find_by_id:

# @user = User.find(params[:id])    # original code
@user = User.find_by_id(params[:id])
if @user
    # found!
else
    # not found
end

This should be faster than a separate exists? check.

EDIT: Note that as @Miguelgraz commented, in Rails 4 you should instead say User.find_by(id: params[:id]). Same functionality, but now the implementation won't need method_missing.




回答3:


throwing the exception is the expected behavior.

in fact in the normal course of events if you let the exception go unhandled your rails server will return the proper 404 page not found error.

if you'd like for it to return nil you can catch it yourself:

begin
  @model = Model.find(id_provided)
rescue ActiveRecord::RecordNotFound => e
  @model = nil
end



回答4:


If you want the exception to be thrown in find_by_attributes flavors of the finder methods, you can use the bang! version of the method.

For example,

Model.find_by_category!(a_category_value)

will throw RecordNotFound if no match is found.

I found this to be DRY in scenarios like RESTful controllers, where I have a common error handler for the exception and I want my actions to behave consistently when a resource matching the given parameters is not found.




回答5:


You can check if the record exists before fetching it.

@model = Model.find(id) if Model.exists?(id)



回答6:


Rails 4 Method

if user = User.find_by(id: params[:id]) 
  #do something with user
else
  #throw error or redirect
  raise ActiveRecord::RecordNotFound
end



回答7:


You can use find_by with the required attribute (in your case the id) this will return nil instead of giving an error if the given id is not found.

Model.find_by_id(id_value)

You could also use where but you have to know that where return an active record relation with zero or more records you need to use first to return only one record or nil in case zero records return.

Model.where(id: id_value).first



回答8:


You can simply use:

user = User.find(10) rescue nil


来源:https://stackoverflow.com/questions/4966430/rails-2-model-find1-gives-activerecord-error-when-id-1-does-not-exist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!