没有记录时使用nil的find()


96

在我当前的Rails程序中,当我使用类似

 user = User.find(10)

当没有ID = 10的用户时,我将遇到类似以下的异常:

ActiveRecord::RecordNotFound: Couldn't find User with ID=10

我可以得到nil而不是引发异常,所以当我做类似的事情时:

unless user = Challenge.find(10)
  puts "some error msg"         
end

我只想在没有记录且不想使用开始/救援时得到nil

谢谢


Answers:


171

是的,只需:

Challenge.find_by_id(10)

对于Rails 4和5:

Challenge.find_by(id: 10)

11
奇!我永远都不会猜到.find_by_*会返回nil ,而不会返回.find
2014年

这在rails 4中已更改,请参见此答案stackoverflow.com/a/26885027/1438478,以了解通过特定属性查找项目的新方法。
鹰眼2015年

我发现Rails 4.2出现了一个奇怪的问题,即当您将散列作为“ x”传递给 Something.find_by(id: x)它时,它将创建一个SQL语句,该散列的所有属性/值对都作为WHERE子句的一部分。在我看来就像是一个Rails的错误。
提洛

Rails(3、4或5)find_by_...为模型包含的每个属性生成动态查找器:id。因此,Challenge.find_by_id(10)无论Rails版本如何,都可以正常工作。
阿塔

如下面的@MohamedIbrahim所指定,您还可以执行以下操作:Challenge.find(10) rescue nil
Hallgeir Wilhelmsen

31

在Rails 4中,find_by_id不赞成使用动态查找器(例如在接受的答案中使用的查找器)。

继续前进,您应该使用新的语法:

Challenge.find_by id: 10

4
如果有人像我一样对此感到困惑:这Challenge.find_by(id: 10)是另一种写法
Devin Howard

14

您可以使用ActiveRecord查询界面来做到这一点。

这将返回nil,而不是引发Exception

  User.where(:id => 10).first

使用它而不是使用find_by_id它的原因是它可以从Rails 3到4移植。在rails 4中,它是find_by(:id => 10)
基因

5

您为什么不简单地捕获异常?您的案子看起来完全像是针对什么例外情况:

begin
  user = User.find(10)
rescue ActiveRecord::RecordNotFound
  puts "some error msg"
end

如果要从救援块中的错误中恢复(例如,通过设置占位符用户(空模式)),则可以在此块下继续执行代码。否则,您可能只是将所有用于“快乐情况”的代码放在“开始”和“救援”之间的代码段中。


顺便说一句:begin…end如果您已经有一个块,例如控制器方法,您甚至不需要该块。在这种情况下,您唯一需要的额外行就是该rescue行。比nil使用if语句进行检查要优雅得多,而且更易于处理。
morgler '17


4

对于那些苦苦挣扎的人来说,无论andrails版本如何findand find_by方法都会引发异常!

有一个选项(即raise_not_found_error)可以设置为false,但是当falsey时make find方法也不会引发异常。

因此,针对蒙古人用户的解决方案是令人讨厌的代码:

User.where(id: 'your_id').first # argghhh

您如何看待穆罕默德·易卜拉欣的零救助方案?似乎比.where(email: params[:email]).first我优雅。
Wylliam Judd

1
我宁可不使用该rescue语法,因为它可以隐藏的问题,如错别字
克里斯蒂亚诺门东萨

我用@morgler的解决方案结束了。
威廉·贾德

2

就像:

user = User.find(10) rescue nil

1
我宁愿更具体地说明预期将要挽救的错误,在这种情况下为ActiveRecord :: RecordNotFound。作为上指出此答案由@morgler
luizrogeriocn

2
我个人认为这是最好的答案。我已经在告诉我的代码,如果找不到该用户该怎么办if user...else
Wylliam Judd '18

0

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

user = Challenge.find_by_id(id_value)

或者您可以使用新格式:

user = Challenge.find_by id: id_value

您还可以使用where,但是您必须知道where返回具有零个或多个记录的活动记录关系,您需要首先使用它来仅返回一个记录,否则需要返回nil,以防零记录返回。

user = Challenge.where(id: id_value).first
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.