我正在使用Rails 2.3.5,如果我给Model.find(1)
并且如果1不在数据库中,则返回ActiveRecord错误。是否应该像nil
一样返回Model.find_by_column('..')
?
答案 0 :(得分:56)
这是预期的行为。我认为大卫自己解释得最好,所以这里引用了Ruby,S.,Thomas,D。& Hansson,D.H.,2009。Agile Web Development with Rails,Third Edition Third Edition。,Pragmatic Bookshelf(p.330)。
使用由...驱动的取景器时 主键,你正在寻找一个 特别记录。你期待它 存在。对Person.find(5)的调用是 基于我们对人的了解 表。我们想要一个id为的行 5.如果此调用不成功 - 如果id为5的记录已经成功 被毁 - 我们是一个例外 情况。这要求提高 一个例外,所以Rails加注 记录不存在。
另一方面, 使用标准进行搜索的查找程序 正在寻找一场比赛。所以, Person.find的(:第一, :conditions =>“name ='Dave'”)是 相当于告诉数据库(如 一个黑盒子)“给我第一个人 名为Dave的行。“这 表现出截然不同的 检索方法;我们前面不确定我们会得到一个结果。 结果集完全可能 可能是空的。因此,返回nil in 搜索的发现者的情况 查找器的一行和一个空数组 搜索多行是 自然的,非感性的反应。
答案 1 :(得分:24)
如果您真的不想要例外,可以使用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?
检查更快。
编辑:请注意,正如@Miguelgraz评论的那样,在Rails 4中你应该说User.find_by(id: params[:id])
。功能相同,但现在实现不需要method_missing
。
答案 2 :(得分:5)
抛出异常是预期的行为。
实际上在正常的事件过程中,如果你让异常处理不当,你的rails服务器将返回正确的404页面未找到错误。
如果你想让它返回零,你可以自己抓住它:
begin
@model = Model.find(id_provided)
rescue ActiveRecord::RecordNotFound => e
@model = nil
end
答案 3 :(得分:2)
如果你想在finder方法的find_by_attributes风格中抛出异常,你可以使用爆炸!该方法的版本。
例如,
Model.find_by_category!(a_category_value)
如果找不到匹配项,将抛出RecordNotFound。
我发现这在RESTful控制器这样的场景中是干的,我有一个常见的异常错误处理程序,我希望我的动作在找不到与给定参数匹配的资源时表现一致。
答案 4 :(得分:1)
Rails 4方法
if user = User.find_by(id: params[:id])
#do something with user
else
#throw error or redirect
raise ActiveRecord::RecordNotFound
end
答案 5 :(得分:0)
您可以在获取记录之前检查记录是否存在。
@model = Model.find(id) if Model.exists?(id)
答案 6 :(得分:0)
您可以将 find_by 与必需属性(在您的情况下为id)一起使用,如果找不到给定的ID,则返回nil而不是给出错误。
Model.find_by_id(id_value)
你也可以使用 where ,但你必须知道,如果返回与零个或多个记录的活动记录关系,你需要首先使用它来返回一个记录,如果零记录返回则需要nil。
Model.where(id: id_value).first
答案 7 :(得分:-1)
您可以简单地使用:
user = User.find(10) rescue nil