レコードがない場合にnilを指定してfind()


95

私のようなものを使用するときの私の現在のレールプログラムで

 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を取得したいだけで、begin / rescueを使用したくない

ありがとう


回答:


170

はい、実行してください:

Challenge.find_by_id(10)

Rails 4および5の場合:

Challenge.find_by(id: 10)

11
変!が.find_by_*nilを返し、nullが返されないことを私は決して想像し.findませんでした。
ddavison 2014

これはRails 4で変更されました。特定の属性でアイテムを検索する新しい方法については、この回答stackoverflow.com/a/26885027/1438478を参照してください。
Fralcon、2015年

Rails 4.2で奇妙な問題が見つかりました。ハッシュを「x」として渡す Something.find_by(id: x)と、WHERE句の一部としてハッシュのすべての属性と値のペアを含むSQLステートメントが作成されます。Railsのバグのようです。
Tilo

Rails(3、4、または5)はfind_by_...、モデルに含まれるすべての属性に対して動的ファインダーを生成します:id。したがって、Challenge.find_by_id(10)Railsのバージョンに関係なく動作するはずです。
2017

以下@MohamedIbrahimによって指定されているように、あなたも行うことができます:Challenge.find(10) rescue nil
Hallgeirウィルヘルム

31

Rails 4では、動的なファインダー(find_by_id受け入れられた回答で使用されていたものなど)は非推奨になりました。

今後は、新しい構文を使用する必要があります。

Challenge.find_by id: 10

4
他の誰かが私のようにこれで混乱している場合:Challenge.find_by(id: 10)これを書くもう1つの方法
Devin Howard

14

ActiveRecordクエリインターフェイスを使用するだけで、少しハックできます。

これは例外を発生させる代わりにnilを返します

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

これを使用するのではなく、find_by_idRails 3から4に移植できるためです。Rails4ではfind_by(:id => 10)です。
Gene

5

なぜ例外をキャッチしないのですか?あなたのケースは例外が作られたものと全く同じように見えます:

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

レスキューブロックのエラーから回復する場合(プレースホルダーユーザー(nullパターン)を設定するなど)、このブロックの下のコードを続行できます。それ以外の場合は、「ハッピーケース」のすべてのコードを「begin」と「rescue」の間のブロックに置くだけです。


ところでbegin…end、コントローラーメソッドなどのブロックが既にある場合は、ブロックは必要ありません。その場合、必要な唯一の追加の行はrescue行です。はるかにエレガントをチェックするよりも扱いやすいnilif声明。
モーグラー2017

4

あなたはこれを試すことができます Challenge.exists?(10)


7
追加のSQLリクエストになります
fl00r

それでも、テストにはこれが適していると思います
SomeSchmo 2017

戻り値を気にせず、DB内のレコードの存在を気にする場合にのみ使用してください
Filip Bartuzi

4

mongoidで苦労している人にとって、レールのバージョンに関係なくfindfind_byメソッドとメソッドの両方が例外を発生させることがわかりました

あるオプション(すなわちraise_not_found_error falseに設定することができます)が、falseyが行ったときにfindこの方法が同様に昇給の例外にしません。

したがって、mongoidユーザーの解決策は嫌なコードです。

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

mohamed-ibrahimによるレスキューnilソリューションについてどう思いますか?.where(email: params[:email]).first私より優雅に見えます。
ウィリアムジャッド

1
rescueタイプミスなどの問題を隠すことができるので、私はむしろその構文を使用しません
CristianoMendonçaJan

私は@morglerのソリューションを使用しました。
ウィリアムジャッド

2

と同じくらい簡単:

user = User.find(10) rescue nil

1
私はむしろ、救われると予想されるエラーについてより具体的にしたいと思います。この場合はActiveRecord :: RecordNotFoundです。@morglerによってこの回答で指摘されたように
luizrogeriocn

2
私は個人的にこれが最良の答えだと思います。ユーザーが見つからない場合のif user...else
対処方法を

0

必要な属性(あなたの場合はid)を指定してfind_byを使用すると、指定されたIDが見つからない場合にエラーを返す代わりにnilを返します。

user = Challenge.find_by_id(id_value)

または、新しい形式を使用できます。

user = Challenge.find_by id: id_value

whereを使用することもできますが、0またはそれ以上のレコードを持つアクティブレコードリレーションを返すwhereは、最初に使用して1つのレコードのみを返すか、ゼロのレコードが返された場合はnilを返す必要があることを知っておく必要があります。

user = Challenge.where(id: id_value).first
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.