0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

find find_by whereメソッドの違いについて

Last updated at Posted at 2024-09-29

レコードの検索時にfind find_by whereメソッドを使用していますが、
なんとなくフィーリングで使っていたので、それぞれの違いについてまとめてみました。

findメソッド

findメソッドは、レコードの主キー(ID)を指定して、1件または複数のレコードを返します。重要なのは、findメソッドは与えられたIDに対応するレコードが存在することを前提としており、IDが存在しない場合は例外(ActiveRecord::RecordNotFound)が発生します。つまり、nilを返さずにエラーになります。

sample.rb
#IDが1のユーザーを取得
user = User.find(1)
 User Load (0.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
`=> #<User id: 1, email: "test_user0@gmail.com", created_at: "2024-08-22 20:12:19.678646000 +0900", updated_at: "2024-08-25 20:20:16.811749000 +0900">`

# 存在しないIDで検索。例外が発生(ActiveRecord::RecordNotFound)
user = User.find(999999999999)
User Load (8.6ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 999999999999 LIMIT 1
ActiveRecord::RecordNotFound: Couldn't find User with 'id'=999999999999
from /usr/local/bundle/gems/activerecord-6.1.7.4/lib/active_record/core.rb:353:in `find'

特徴

・主キー(ID)を使ってレコードを取得するので、
基本的には1件のレコードを取得するためのメソッド

・結果が存在しない場合は、nilを返さずに例外が発生する

・配列で複数のIDを指定することで、複数のレコードを一度に取得できる

find_byメソッド

find_byメソッドは、ID以外の任意のカラムに基づいて検索する。条件に合致する最初のレコードを返す。該当するレコードが存在しない場合は例外は発生せずに、nilが返されます。

sample.rb

# メールアドレスを指定してユーザーのレコードを検索。
user = User.find_by(email: "test_user0@email.com")      
User Load (2.2ms)  SELECT * FROM users WHERE users.email = 'test_user0@gmail.com' LIMIT 1
=> <User id: 1, email: "test_user0@email.com", created_at: "2020-08-22 20:12:19.678646000 +0900", updated_at: "2020-08-25 20:20:16.811749000 +0900">

# 存在しないメールアドレスで検索。
user = User.find_by(email: "**********")
User Load (7.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = '**********' LIMIT 1
=> nil

特徴

任意のカラムを使って検索することができる。emailやnameなどの特定の属性に対して検索することができるので、柔軟な検索が可能

・複数の条件に合致する場合でも、最初に見つかったレコード1件のみを返す(複数のレコードを取得したい場合はwhereメソッドを使用する)

該当するレコードがない場合はnilを返すそのため、存在しない可能性がある処理に対しても柔軟に対応できる(userがnilの場合の処理を書くなど)

whereメソッド

whereメソッドは、テーブル内の条件に一致したレコードを配列の形で返します。1つのオブジェクトではなく、複数のまとまったオブジェクトが返ってくるのが特徴です。検索結果が存在しない場合は空の配列を返し、1件でも結果があれば、配列の形で返します。

sample.rb
# USERのIDが5以上のユーザーを検索
User.where("id > ?", 5)
=>   User Load (9.0ms)  SELECT `users`.* FROM `users` WHERE (id > 5)
[#<User id: 6, email: "test_user5@email.com", created_at: "2020-08-22 20:12:20.869230000 +0900", updated_at: "2020-08-22 20:12:20.869230000 +0900">,
 #<User id: 7, email: "test_user6@email.com", created_at: "2020-08-22 20:12:21.117923000 +0900", updated_at: "2020-08-22 20:12:21.117923000 +0900">,
 #<User id: 8, email: "test_user7@email.com", created_at: "2020-08-22 20:12:21.350857000 +0900", updated_at: "2020-08-22 20:12:21.350857000 +0900">

# 複数の条件を指定してレコードを検索することも可能。
User.where("id > ? AND gender = ?", 5, 'male')
#<User id: 28, email: "tester012@email.com", created_at: "2020-09-17 21:58:40.152471000 +0900", updated_at: "2024-09-17 21:58:52.186041000 +0900",
 #<User id: 30, email: "tester013@email.com", created_at: "2020-09-17 21:29:03.588729000 +0900", updated_at: "2024-09-17 21:29:19.207693000 +0900"

# 他のActiveRecordのメソッド 例のようにorderメソッドと組み合わせて使用することもできる。
 User.where("id > ?", 5).order("created_at DESC")
=>   User Load (1.3ms)  SELECT `users`.* FROM `users` WHERE (id > 5) ORDER BY created_at DESC
[#<User id: 38, email: "tester012@gmail.com", created_at: "2024-09-17 21:58:40.152471000 +0900", updated_at: "2024-09-17 21:58:52.186041000 +0900">,
 #<User id: 37, email: "test@email.com", created_at: "2024-09-17 21:29:03.588729000 +0900", updated_at: "2024-09-17 21:29:19.207693000 +0900">

# 結果が存在しない場合は、例外は発生せず、空のリレーション(`ActiveRecord::Relation`オブジェクト)を返します。
User.where(age: 200)
=>   User Load (9.2ms)  SELECT `users`.* FROM `users` WHERE `users`.`age` = 200
[]

特徴

・whereメソッドは、複数のレコードを取得する際に使用する。検索結果は、ActiveRecord:Relationオブジェクトという配列のような形で返ってくる。

検索結果が存在しない場合は、例外処理は発生せずに、空のリレーションを返す。このオブジェクトは配列のように扱えるため、結果が空の場合は[]と表示されるが、実際に返されているのはActiveRecord::Relationとなる。

・findやfind_byとの大きな違いは、前述の通り、複数のレコードを取得できること。findはプライマリーキー(主キー)を使用して1件のレコードを取得し、find_byは条件指定して見つかった最初の1件のレコードを返す(※)。いずれも単一のレコードを返さない。

一方で、whereメソッドは、条件に合致する複数のレコードを取得することができる。そのため、アプリケーションの検索機能の実装で頻繁に使用される。

※ find_byは複数の条件を指定できますが、最初に見つかった1件のレコードのみを返します。そのため、複数のレコードを取得することはできません。

find find_by whereの違い

メソッド 主キー検索 条件検索 結果がない場合 戻り値
find 主キーのみ 不可 例外が発生 1件または複数のレコード
find_by 可能 可能 nilを返す 1件のレコード
wherer 不可 可能 空のリレーション ActiveRecord::Relationオブジェクト(複数のレコード)

find find_by whereメソッドについて検索方法、検索結果が存在しない場合、
メソッドの返り値をおおざっぱにまとめると上記の表の通りです。
使い分けとしては、だいたい下記のシチュエーションで使用することになると思います。

find ・・・idの値が明確で、そのidのデータを取得したい場合
find_by ・・・ idの値が不明。id以外のカラムを検索条件としたい場合
where ・・・ id以外のカラムの検索条件で、複数の検索結果を取得したい場合

以上、find find_by whereメソッドの解説でした。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?