31

我正在使用 Rails 2.3.5,如果我给出Model.find(1)并且 1 不在数据库中,它会返回 ActiveRecord 错误。它应该nil像 的情况一样返回Model.find_by_column('..')吗?

4

8 回答 8

60

这是预期的行为。我认为 David 自己解释得最好,所以这里引用 Ruby, S., Thomas, D. & Hansson, DH, 2009. Agile Web Development with Rails , Third Edition 第三版., Pragmatic Bookshelf (p.330) .

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

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

于 2011-02-11T07:23:23.440 回答
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

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

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

于 2011-03-10T14:52:40.253 回答
7

抛出异常是预期的行为。

事实上,在正常的事件过程中,如果您不处理异常,您的 rails 服务器将返回正确的 404 page not found 错误。

如果你想让它返回 nil 你可以自己抓住它:

begin
  @model = Model.find(id_provided)
rescue ActiveRecord::RecordNotFound => e
  @model = nil
end
于 2011-02-11T07:18:31.790 回答
3

如果您希望在查找器方法的 find_by_attributes 风格中抛出异常,您可以使用 bang!方法的版本。

例如,

Model.find_by_category!(a_category_value)

如果找不到匹配项,将抛出 RecordNotFound。

我发现这在 RESTful 控制器等场景中是 DRY 的,在这种情况下,我有一个常见的异常错误处理程序,并且我希望我的操作在未找到与给定参数匹配的资源时表现一致。

于 2013-04-30T01:58:36.523 回答
1

您可以在获取记录之前检查记录是否存在。

@model = Model.find(id) if Model.exists?(id)
于 2011-02-11T13:07:58.967 回答
1

Rails 4 方法

if user = User.find_by(id: params[:id]) 
  #do something with user
else
  #throw error or redirect
  raise ActiveRecord::RecordNotFound
end
于 2014-12-02T16:18:43.930 回答
1

您可以将find_by与必需的属性(在您的情况下为 id)一起使用,如果未找到给定的 id,这将返回 nil 而不是给出错误。

Model.find_by_id(id_value)

您也可以使用where但您必须知道 where 返回具有零个或多个记录的活动记录关系,您首先需要使用它来仅返回一条记录,或者在零记录返回的情况下返回 nil。

Model.where(id: id_value).first
于 2016-10-04T09:11:08.460 回答
0

您可以简单地使用:

user = User.find(10) rescue nil
于 2016-12-19T11:50:18.283 回答