Rails 2:当id 1不存在时,Model.find(1)给出ActiveRecord错误

rub*_*nce 31 ruby-on-rails ruby-on-rails-2

我正在使用Rails 2.3.5,如果我给出Model.find(1),如果1不在数据库中,则返回ActiveRecord错误.它应该nil像在案件中一样返回Model.find_by_column('..')吗?

Mad*_*bæk 60

这是预期的行为.我认为大卫自己解释这是最好的,所以这里引用了Ruby,S.,Thomas,D.和Hansson,DH,2009.使用Rails的敏捷Web开发,第三版第三版.,实用书架(第330页) .

当您使用由主键驱动的查找器时,您正在寻找特定记录.你希望它存在.对Person.find(5)的调用基于我们对people表的了解.我们希望id为5的行.如果此调用不成功 - 如果id为5的记录已被破坏 - 我们处于异常情况.这要求引发异常,因此Rails会引发RecordNotFound.

另一方面,使用搜索条件的查找器正在寻找匹配项.因此,Person.find(:first,:conditions =>"name ='Dave'")相当于告诉数据库(作为黑盒子)"给我第一个名为Dave的人行."这个展览一种截然不同的检索方法; 我们前面不确定我们会得到一个结果.结果集完全可能是空的.因此,在搜索一行的查找器和搜索多行的查找器的空数组的情况下返回nil是自然的,非响应的响应.

  • 每个人都来到Rails并获得例外时,会重复对此的困惑.混淆/惊讶是因为`find`是一个软动词,并没有明确说明存在的精确性或预知.当然,我们现在已经背负了这个决定,但只要新人开始使用Rails就会问这个问题. (8认同)
  • 如果希望在finder方法的find_by_attributes风格中引发异常,则可以使用爆炸!方法的版本。例如,如果找不到匹配项,Model.find_by_category!(a_category_value)将抛出RecordNotFound。我发现这在诸如RESTful控制器之类的场景中是DRY的,那里我有一个通用的异常处理程序,并且我希望我的动作在找不到与给定参数匹配的资源时表现一致。 (2认同)

Pau*_*rth 25

如果你真的不想要例外,你可以使用find_by_id:

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

这应该比单独exists?检查更快.

编辑:请注意,正如@Miguelgraz评论的那样,在Rails 4中你应该说User.find_by(id: params[:id]).功能相同,但现在不需要实现method_missing.


Kal*_*dae 6

抛出异常是预期的行为.

事实上,在正常的事件过程中,如果你让异常处理不当,你的rails服务器将返回正确的404页面未找到错误.

如果你想让它返回零你可以自己捕捉它:

begin
  @model = Model.find(id_provided)
rescue ActiveRecord::RecordNotFound => e
  @model = nil
end
Run Code Online (Sandbox Code Playgroud)