しっかりと、どう違う
という説明ができなかったので、まとめました。
findメソッドとは
各モデルのid
を検索キーとしてデータを取得するメソッド
id以外の条件で検索不可
取得したいデータのidの値が、1、10と具体的に分かっている場合
に使用する。
(例)Aiueoモデルからid=1のデータを取得したい場合
irb(main):001:0> Aiueo.find(1)
Aiueo Load (0.9ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
=> #<Aiueo id: 1, name: "名前0", title: "タイトル0", created_at: "2018-03-13 04:39:22", updated_at: "2018-03-13 04:39:22">
該当データがない場合は、ActiveRecord::RecordNotFound
が返ってくる。
つまり、エラー
が返ってくるということ。
irb(main):006:0> Aiueo.find(1000000)
Aiueo Load (0.4ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."id" = $1 LIMIT $2 [["id", 1000000], ["LIMIT", 1]]
ActiveRecord::RecordNotFound: Couldn't find Aiueo with 'id'=1000000
find_byメソッドとは
各モデルをid以外の条件で
検索するメソッド(idでも検索可能)
複数の検索条件を指定可能
返ってくる結果は、最初にヒットした1件のみ
id及びid以外の条件が分かっている場合
、その条件に該当する最初のデータを取得したい場合に使用する。
(例)Aiueoモデルからタイトルが「タイトル0」のデータを取得する場合
irb(main):004:0> Aiueo.find_by(title: "タイトル0")
Aiueo Load (0.4ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."title" = $1 LIMIT $2 [["title", "タイトル0"], ["LIMIT", 1]]
=> #<Aiueo id: 1, name: "名前0", title: "タイトル0", created_at: "2018-03-13 04:39:22", updated_at: "2018-03-13 04:39:22">
該当データがない場合は、nil
が返ってくる。
irb(main):007:0> Aiueo.find_by(title: "タイトル")
Aiueo Load (0.6ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."title" = $1 LIMIT $2 [["title", "タイトル"], ["LIMIT", 1]]
=> nil
whereメソッド
各モデルをid以外の条件で
検索する場合
該当するデータ全てが返ってくる。
(例)Aiueoモデルからタイトルが「タイトル0」のデータを取得する場合
irb(main):005:0> Aiueo.where(title: "タイトル0")
Aiueo Load (1.0ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."title" = $1 LIMIT $2 [["title", "タイトル0"], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Aiueo id: 1, name: "名前0", title: "タイトル0", created_at: "2018-03-13 04:39:22", updated_at: "2018-03-13 04:39:22">]>
find_byの結果と違い、先頭にActiveRecord::Relation
の文字が。
ActiveRecord::Relation は、検索クエリを組み立てるもの
で、検索結果のオブジェクト
とは異なるものである、とのこと。
う〜ん、むずかしい・・・
find
、find_by
メソッドは、検索結果のインスタンス(オブジェクト)
(簡単にいうと、検索結果のデータがつまったもの)を返すが、
where
メソッドは、検索結果をオブジェクトとして返しているのではなく、検索するためのプログラムを発生させ、結果を表示しているだけ
の状態(うまく説明できない・・・)
なので、whereでは、取得したデータから特定カラムのデータを取得しようとするとエラーになる。
irb(main):012:0> @aiueo = Aiueo.where(title: "タイトル0")
Aiueo Load (0.6ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."title" = $1 LIMIT $2 [["title", "タイトル0"], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Aiueo id: 1, name: "名前0", title: "タイトル0", created_at: "2018-03-13 04:39:22", updated_at: "2018-03-13 04:39:22">]>
irb(main):013:0> @aiueo.title
NoMethodError: Aiueo Load (0.4ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."title" = $1 LIMIT $2 [["title", "タイトル0"], ["LIMIT", 11]]
undefined method `title' for #<Aiueo::ActiveRecord_Relation:0x007fef48b8c3a8>
一方、find_byでは、実行結果のインスタンスが返ってきているので、特定カラムのデータも取得できる。
irb(main):014:0> @aiueo = Aiueo.find_by(title: "タイトル0")
Aiueo Load (0.9ms) SELECT "aiueos".* FROM "aiueos" WHERE "aiueos"."title" = $1 LIMIT $2 [["title", "タイトル0"], ["LIMIT", 1]]
=> #<Aiueo id: 1, name: "名前0", title: "タイトル0", created_at: "2018-03-13 04:39:22", updated_at: "2018-03-13 04:39:22">
irb(main):015:0> @aiueo.title
=> "タイトル0"
まとめ
使用区分としては、
idの値が分かっていて、そのidのデータを取得したい場合・・・find
idの値が不明で、id以外のカラムを検索条件としたい場合・・・find_by
id以外のカラムの検索条件で、複数の実行結果を取得したい場合・・・where
こんなところかなと。