Rails 2:当id 1不存在时,Model.find(1)给出ActiveRecord错误
我正在使用Rails 2.3.5,如果我给Model.find(1)
,如果1不在数据库中,则返回ActiveRecord错误。 是否应该像Model.find_by_column('..')
一样返回nil
?
这是预期的行为。 我认为David自己解释了这一点,所以这里引用Ruby,S.,Thomas,D.&Hansson,DH,2009年。“ Rails敏捷Web开发” ,第三版第三版,实用书架(p.330) 。
当您使用由主键驱动的查找程序时,您正在查找特定的logging。 你期望它存在。 Person.find(5)的调用是基于我们对人员表的了解。 我们想要一个id为5的行。如果这个调用不成功 – 如果id为5的logging已经被破坏,我们就处于一个特殊的情况。 这要求提出一个exception,所以Rails提出了RecordNotFound。
另一方面,使用标准search的发现者正在寻找匹配。 所以,Person.find(:first,:conditions =>“name ='Dave'”)等同于告诉数据库(作为黑匣子)“给我第一个有Dave名字的人行”一种明显不同的检索方法; 我们不能确定,我们会得到一个结果。 结果集完全可能是空的。 因此,对于查找一行的查找器返回nil,search多行的查找器返回一个空数组是非常不自然的反应。
如果你真的不想要这个exception,你可以使用find_by_id
:
# @user = User.find(params[:id]) # original code @user = User.find_by_id(params[:id]) if @user # found! else # not found end
这应该比单独的exists?
更快exists?
检查。
编辑:请注意,作为@Miguelgraz评论,在Rails 4中,你应该改为User.find_by(id: params[:id])
。 相同的function,但现在实施将不需要method_missing
。
抛出exception是预期的行为。
事实上在正常的事件过程中,如果让exception处理未处理,您的Rails服务器将返回正确的404页未find错误。
如果你想要它返回零,你可以捕捉它自己:
begin @model = Model.find(id_provided) rescue ActiveRecord::RecordNotFound => e @model = nil end
如果你想在finder方法的find_by_attributes风格中抛出exception,你可以使用bang! 该方法的版本。
例如,
Model.find_by_category!(a_category_value)
如果找不到匹配,将抛出RecordNotFound。
我发现这是DRY在像RESTful控制器,其中我有一个常见的error handling程序的exception,我希望我的行动一致,当没有find与给定的参数匹配的资源行为。
在获取logging之前,您可以检查logging是否存在。
@model = Model.find(id) if Model.exists?(id)
Rails 4方法
if user = User.find_by(id: params[:id]) #do something with user else #throw error or redirect raise ActiveRecord::RecordNotFound end
你可以使用find_by与必要的属性(在你的情况下的id),这将返回零,而不是给出错误,如果没有find给定的ID。
Model.find_by_id(id_value)
你也可以使用where,但是你必须知道在哪里返回一个活动的logging关系,有零个或多个logging,你需要先使用返回一个logging,否则返回零。
Model.where(id: id_value).first
你可以简单地使用:
user = User.find(10) rescue nil