0
0

More than 1 year has passed since last update.

Railsにてfind, find_by, whereの違いについて

Posted at

はじめに

Railsでモデルの検索に使えるメソッドfind, find_by, whereの使い方や違いについて紹介します。

結論

find find_by where
括弧の中に指定するものは? id(複数可能) 条件 条件
戻り値 条件に一致するデータ全て 条件に一致する最初の1件だけ 条件に一致するデータ全て
戻り値の型 モデルのインスタンス (結果が複数の場合は配列) モデルのインスタンス ActiveRecord::Relationのインスタンス
検索結果がない場合 例外発生 nilを返す 空きのActiveRecord::Relationを返す

動作確認

テストデータ

irb(main):015:0> Word.all
  Word Load (4.5ms)  SELECT `words`.* FROM `words`
=>
[#<Word:0x00007f21a3d7ed78
  id: 1,
  vocabulary: "詐欺",
  pronunciation: "さぎ",
  viewing: 10,
  meaning: "相手をだますこと",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00>,
 #<Word:0x00007f21a3d7e968
  id: 2,
  vocabulary: "鷺",
  pronunciation: "さぎ",
  viewing: 53,
  meaning: "鳥の一種類",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.278526000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.278526000 UTC +00:00>,
 #<Word:0x00007f21a3d7e800
  id: 3,
  vocabulary: "子供",
  pronunciation: "こども",
  viewing: 11,
  meaning: "年のいかない幼い者",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00>,
 #<Word:0x00007f21a3d7e698
  id: 4,
  vocabulary: "大人",
  pronunciation: "おとな",
  viewing: 20,
  meaning: "成長して一人前になった人",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00>]

括弧の中に指定するものは?

find

モデルののIDを指定して検索する。IDは1個または複数を指定可能。

★1個指定したとき
irb(main):016:0> Word.find(1)
  Word Load (2.5ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` = 1 LIMIT 1
=>
#<Word:0x00007f21a277bb20
 id: 1,
 vocabulary: "詐欺",
 pronunciation: "さぎ",
 viewing: 10,
 meaning: "相手をだますこと",
 example: nil,
 created_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00,
 updated_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00>

★複数指定したとき
irb(main):017:0> Word.find(1,2)
  Word Load (1.1ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` IN (1, 2)
=>
[#<Word:0x00007f21a26b6c58
  id: 1,
  vocabulary: "詐欺",
  pronunciation: "さぎ",
  viewing: 10,
  meaning: "相手をだますこと",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00>,
 #<Word:0x00007f21a26b6b90
  id: 2,
  vocabulary: "鷺",
  pronunciation: "さぎ",
  viewing: 53,
  meaning: "鳥の一種類",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.278526000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.278526000 UTC +00:00>]

★複数指定したときは配列でもOK
irb(main):021:0> Word.find([1,3,4])
  Word Load (1.0ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` IN (1, 3, 4)
=>
[#<Word:0x00007f21a30829a8
  id: 1,
  vocabulary: "詐欺",
  pronunciation: "さぎ",
  viewing: 10,
  meaning: "相手をだますこと",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00>,
 #<Word:0x00007f21a30828b8
  id: 3,
  vocabulary: "子供",
  pronunciation: "こども",
  viewing: 11,
  meaning: "年のいかない幼い者",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00>,
 #<Word:0x00007f21a30827f0
  id: 4,
  vocabulary: "大人",
  pronunciation: "おとな",
  viewing: 20,
  meaning: "成長して一人前になった人",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00>]

find_by

条件にモデルの属性: 値の形を指定して検索する。

irb(main):024:0> Word.find_by(vocabulary: "鷺")
  Word Load (1.2ms)  SELECT `words`.* FROM `words` WHERE `words`.`vocabulary` = '鷺' LIMIT 1
=>
#<Word:0x00007f21a3da92d0
 id: 2,
 vocabulary: "鷺",
 pronunciation: "さぎ",
 viewing: 53,
 meaning: "鳥の一種類",
 example: nil,
 created_at: Sun, 23 Jul 2023 04:25:33.278526000 UTC +00:00,
 updated_at: Sun, 23 Jul 2023 04:25:33.278526000 UTC +00:00>

where

SQL文のwhere句に書くような感覚で条件指定して検索をする。
モデルの属性: 値とかモデルの属性 > 値みたいに

★例1
irb(main):031:0> Word.where(vocabulary: "子供")
  Word Load (0.8ms)  SELECT `words`.* FROM `words` WHERE `words`.`vocabulary` = '子供'
=>
[#<Word:0x00007f21a30dc8e0
  id: 3,
  vocabulary: "子供",
  pronunciation: "こども",
  viewing: 11,
  meaning: "年のいかない幼い者",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00>]

★例2
irb(main):036:0> Word.where("id > 2")
  Word Load (1.1ms)  SELECT `words`.* FROM `words` WHERE (id > 2)
=>
[#<Word:0x00007f21a3d9ed30
  id: 3,
  vocabulary: "子供",
  pronunciation: "こども",
  viewing: 11,
  meaning: "年のいかない幼い者",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00>,
 #<Word:0x00007f21a3d9e740
  id: 4,
  vocabulary: "大人",
  pronunciation: "おとな",
  viewing: 20,
  meaning: "成長して一人前になった人",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00>]

★例3(id=2以外を取得)
irb(main):039:0> Word.where("id <> 2")
  Word Load (1.1ms)  SELECT `words`.* FROM `words` WHERE (id <> 2)
=>
[#<Word:0x00007f21a3c45a10
  id: 1,
  vocabulary: "詐欺",
  pronunciation: "さぎ",
  viewing: 10,
  meaning: "相手をだますこと",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00>,
 #<Word:0x00007f21a3c458d0
  id: 3,
  vocabulary: "子供",
  pronunciation: "こども",
  viewing: 11,
  meaning: "年のいかない幼い者",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.298938000 UTC +00:00>,
 #<Word:0x00007f21a3c45808
  id: 4,
  vocabulary: "大人",
  pronunciation: "おとな",
  viewing: 20,
  meaning: "成長して一人前になった人",
  example: nil,
  created_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00,
  updated_at: Sun, 23 Jul 2023 04:25:33.321767000 UTC +00:00>]

戻り値

find

(「括弧の中に指定するものは?」と検証内容がかぶるため割愛します。)

find_by

irb(main):045:0> Word.find_by(pronunciation: "さぎ")
  Word Load (8.4ms)  SELECT `words`.* FROM `words` WHERE `words`.`pronunciation` = 'さぎ' LIMIT 1
=>
#<Word:0x00007f21a308b9b8
 id: 1,
 vocabulary: "詐欺",
 pronunciation: "さぎ",
 viewing: 10,
 meaning: "相手をだますこと",
 example: nil,
 created_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00,
 updated_at: Sun, 23 Jul 2023 04:25:33.251697000 UTC +00:00>

pronunciation: "さぎ"は2件存在するが、最初の1件だけ返されました。

where

(「括弧の中に指定するものは?」と検証内容がかぶるため割愛します。)

戻り値の型

find

★結果が1件の場合、Wordのインスタンスを返す
irb(main):052:0> Word.find(4).class
  Word Load (2.7ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` = 4 LIMIT 1
=> Word(id: integer, vocabulary: string, pronunciation: string, viewing: integer, meaning: text, example: text, created_at: datetime, updated_at: datetime)

★結果が複数の場合、配列を返す
irb(main):053:0> Word.find([2,4]).class
  Word Load (1.4ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` IN (2, 4)
=> Array

★配列を返したとしても中身はWordのインスタンスの集合
irb(main):054:0> Word.find([2,4])[1].class
  Word Load (2.7ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` IN (2, 4)
=> Word(id: integer, vocabulary: string, pronunciation: string, viewing: integer, meaning: text, example: text, created_at: datetime, updated_at: datetime)

find_by

irb(main):058:0> Word.find_by(pronunciation: "さぎ").class
  Word Load (0.9ms)  SELECT `words`.* FROM `words` WHERE `words`.`pronunciation` = 'さぎ' LIMIT 1
=> Word(id: integer, vocabulary: string, pronunciation: string, viewing: integer, meaning: text, example: text, created_at: datetime, updated_at: datetime)

Wordのインスタンスを返す

where

irb(main):066:0> Word.where("id in (2, 4)").class
=> Word::ActiveRecord_Relation

検索結果がない場合

find

irb(main):069:0> Word.find(5)
  Word Load (1.1ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` = 5 LIMIT 1
/usr/local/bundle/gems/activerecord-7.0.4.2/lib/active_record/core.rb:284:in `find': Couldn't find Word with 'id'=5 (ActiveRecord::RecordNotFound)

例外ActiveRecord::RecordNotFoundが発生

find_by

irb(main):070:0> Word.find_by(id: 5)
  Word Load (0.7ms)  SELECT `words`.* FROM `words` WHERE `words`.`id` = 5 LIMIT 1
=> nil

nilを返す

where

irb(main):073:0> Word.where("id > 5")
  Word Load (0.9ms)  SELECT `words`.* FROM `words` WHERE (id > 5)
=> []

空きの配列に見えるが

irb(main):074:0> Word.where("id > 5").class
=> Word::ActiveRecord_Relation

型はActiveRecord_Relationでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0