Railsは初めてです。レコードを見つける方法はたくさんあります。
find_by_<columnname>(<columnvalue>)
find(:first, :conditions => { <columnname> => <columnvalue> }
where(<columnname> => <columnvalue>).first
そして、それらはすべてまったく同じSQLを生成するように見えます。また、複数のレコードを検索する場合も同じことが言えると思います。
find_all_by_<columnname>(<columnvalue>)
find(:all, :conditions => { <columnname> => <columnvalue> }
where(<columnname> => <columnvalue>)
どちらを使用するかについて、経験則または推奨事項はありますか?
ニーズに最も合ったものを使用してください。
find
メソッドは通常、IDで行を取得するために使用されます。
Model.find(1)
指定した属性でアイテムが見つからない場合、find
は例外をスローすることに注意してください。 where
(以下で説明するように、属性が見つからない場合は空の配列を返す)を使用して、例外がスローされるのを防ぎます。
find
の他の用途は、通常次のようなものに置き換えられます。
Model.all
Model.first
find_by
は、列内の情報を検索するときにヘルパーとして使用され、命名規則を使用してそのようなものにマップします。たとえば、データベースにname
という名前の列がある場合、次の構文を使用します。
Model.find_by(name: "Bob")
.where
は、従来のヘルパーが実行しない場合にもう少し複雑なロジックを使用できるようにするキャッチオールであり、条件に一致する項目の配列(またはそうでない場合は空の配列)を返します。
whereはActiveRecord :: Relationを返します
次に、find_byの実装を見てみましょう。
def find_by
where(*args).take
end
ご覧のとおりfind_byはwhereと同じですが、1つのレコードのみを返します。このメソッドは、1つのレコードを取得するために使用する必要があり、whereは、いくつかの条件を持つすべてのレコードを取得するために使用する必要があります。
find
とfind_by
には違いがあり、find
は見つからない場合はエラーを返し、find_by
はnullを返します。
.where(email: some_params).first
ではなくfind_by email: "haha"
のようなメソッドを使用すると読みやすくなる場合があります。
Model.find
1-パラメータ:検索するオブジェクトのID。
2-見つかった場合:オブジェクトを返します(1つのオブジェクトのみ)。
3-見つからない場合:ActiveRecord::RecordNotFound
例外を発生させます。
Model.find_by
1-パラメーター:キー/値
例:
User.find_by name: 'John', email: '[email protected]'
2-見つかった場合:オブジェクトを返します。
3-見つからない場合:nil
を返します。
注:ActiveRecord::RecordNotFound
を上げる場合はfind_by!
を使用します
Model.where
1-パラメーター:find_by
と同じ
2-見つかった場合:パラメータに一致する1つ以上のレコードを含むActiveRecord::Relation
を返します。
3-見つからない場合:空のActiveRecord::Relation
を返します。
Rails 4以降、次のことができます。
User.find_by(name: 'Bob')
Railsの同等のfind_by_name
3。
#where
と#find
が十分でない場合は、#find_by
を使用します。
受け入れられた答えは一般的にそれをすべてカバーしていますが、更新のような方法でモデルを使用する予定があり、単一のレコードを取得する場合に備えて、何かを追加したいと思います(誰がid
知っている)、それからfind_by
は行く方法です。なぜなら、レコードを取得し、配列に入れないからです
irb(main):037:0> @kit = Kit.find_by(number: "3456")
Kit Load (0.9ms) SELECT "kits".* FROM "kits" WHERE "kits"."number" =
'3456' LIMIT 1
=> #<Kit id: 1, number: "3456", created_at: "2015-05-12 06:10:56",
updated_at: "2015-05-12 06:10:56", job_id: nil>
irb(main):038:0> @kit.update(job_id: 2)
(0.2ms) BEGIN Kit Exists (0.4ms) SELECT 1 AS one FROM "kits" WHERE
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.5ms)
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" =
1 [["job_id", 2], ["updated_at", Tue, 12 May 2015 07:16:58 UTC +00:00]]
(0.6ms) COMMIT => true
ただし、where
を使用する場合、直接更新することはできません
irb(main):039:0> @kit = Kit.where(number: "3456")
Kit Load (1.2ms) SELECT "kits".* FROM "kits" WHERE "kits"."number" =
'3456' => #<ActiveRecord::Relation [#<Kit id: 1, number: "3456",
created_at: "2015-05-12 06:10:56", updated_at: "2015-05-12 07:16:58",
job_id: 2>]>
irb(main):040:0> @kit.update(job_id: 3)
ArgumentError: wrong number of arguments (1 for 2)
このような場合、次のように指定する必要があります
irb(main):043:0> @kit[0].update(job_id: 3)
(0.2ms) BEGIN Kit Exists (0.6ms) SELECT 1 AS one FROM "kits" WHERE
("kits"."number" = '3456' AND "kits"."id" != 1) LIMIT 1 SQL (0.6ms)
UPDATE "kits" SET "job_id" = $1, "updated_at" = $2 WHERE "kits"."id" = 1
[["job_id", 3], ["updated_at", Tue, 12 May 2015 07:28:04 UTC +00:00]]
(0.5ms) COMMIT => true
リストの両方の#2は廃止されています。ただし、find(params[:id])
は引き続き使用できます。
一般的に、where()
はほとんどの状況で機能します。
ここに素晴らしい投稿があります: http://m.onkey.org/active-record-query-interface
受け入れられた答えとは別に、以下も有効です
Model.find()
はIDの配列を受け入れることができ、一致するすべてのレコードを返します。 Model.find_by_id(123)
も配列を受け入れますが、配列に存在する最初のid値のみを処理します
Model.find([1,2,3])
Model.find_by_id([1,2,3])
モデルUserがあるとします
User.find(id)
IDが指す行を返します。したがって、id = 1の場合、最初の行を返します。戻りタイプはユーザーオブジェクトになります。
User.find_by(email:"[email protected]")
この場合、一致する属性または電子メールで最初の行を返します。戻り型は再びユーザーオブジェクトになります。
User.where(project_id:1)
属性が一致するユーザーテーブル内のすべてのユーザーを返します。ここで返されるタイプは、Userオブジェクトのリストを含むActiveRecord :: Relationオブジェクトになります。
これまでに与えられた答えはすべてOKです。
ただし、興味深い違いの1つは、Model.find
がIDで検索することです。見つかった場合、Model
オブジェクト(単一のレコードのみ)を返しますが、そうでない場合はActiveRecord::RecordNotFound
をスローします。
Model.find_by
はModel.find
と非常に似ており、データベース内の任意の列または列のグループを検索できますが、検索に一致するレコードがない場合はnil
を返します。
一方、Model.where
は、検索に一致するすべてのレコードを含む配列のようなModel::ActiveRecord_Relation
オブジェクトを返します。レコードが見つからなかった場合、空のModel::ActiveRecord_Relation
オブジェクトを返します。
これらがいつでも使用するものを決定するのに役立つことを願っています。