私はRails 2.3.5を使用してModel.find(1)
います.1がデータベースにない場合、ActiveRecordエラーが返されます。nil
の場合のように返されるべきModel.find_by_column('..')
ですか?
8 に答える
これは予期される動作です。これについては David 自身が最もよく説明していると思います。Ruby, S., Thomas, D. & Hansson, DH, 2009. Agile Web Development with Rails , Third Edition Third Edition., Pragmatic Bookshelf (p.330)からの引用です。 .
主キー駆動のファインダを使用すると、特定のレコードを探します。あなたはそれが存在することを期待しています。Person.find(5) の呼び出しは、 people テーブルに関する知識に基づいています。id 5 の行が必要です。この呼び出しが失敗した場合 (id 5 のレコードが破棄された場合)、例外的な状況になります。これは例外の発生を強制するため、Rails は RecordNotFound を発生させます。
一方、基準を使用して検索するファインダーは、一致を探しています。したがって、Person.find(:first, :conditions="name='Dave'") は、データベースに (ブラック ボックスとして) 「Dave という名前を持つ最初の人物の行を教えてください」と伝えることと同じです。これは、検索に対する明らかに異なるアプローチを示しています。結果が得られるかどうかは事前にわかりません。結果セットが空になる可能性は十分にあります。したがって、1 つの行を検索するファインダーの場合は nil を返し、多数の行を検索するファインダーの場合は空の配列を返すことは、例外的ではない自然な応答です。
本当に例外が必要ない場合は、次を使用できます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
。
例外をスローすることは、予期される動作です。
実際、通常のイベントの過程で、例外を未処理のままにしておくと、Rails サーバーは適切な 404 ページが見つからないというエラーを返します。
nil を返したい場合は、自分でキャッチできます。
begin
@model = Model.find(id_provided)
rescue ActiveRecord::RecordNotFound => e
@model = nil
end
ファインダー メソッドの find_by_attributes フレーバーで例外をスローする場合は、bang! を使用できます。メソッドのバージョン。
例えば、
Model.find_by_category!(a_category_value)
一致するものが見つからない場合、RecordNotFound がスローされます。
これは、RESTful コントローラーのようなシナリオで DRY であることがわかりました。このシナリオでは、例外に対して一般的なエラー ハンドラーがあり、指定されたパラメーターに一致するリソースが見つからない場合にアクションを一貫して動作させたいと考えています。
Rails 4 メソッド
if user = User.find_by(id: params[:id])
#do something with user
else
#throw error or redirect
raise ActiveRecord::RecordNotFound
end
取得する前に、レコードが存在するかどうかを確認できます。
@model = Model.find(id) if Model.exists?(id)