この記事ではfindとfind_byの違いについて分かりやすく伝わるように書いてみようと思います。
わかりにくいところがあれば参考記事も確認して、しっかりと理解していただければ幸いです。
#findとは
- idを検索キーとして、取得したいモデルから特定のデータを取得する方法
- findを使用する場合には、id以外では検索できない
- 要するに、取得したいデータのidが分かっている場合に使用するといい
- 検索の仕方は モデル名.find(id) 例:User.find(1)
####使用方法
例えばUserモデルにあるtaroさんのデータが欲しいとします。
その場合、findで検索するとなると id で検索してあげる必要があります。
Userモデル
id | name | age |
---|---|---|
1 | taro | 23 |
2 | jiro | 20 |
3 | sabu | 18 |
User.find(1)
→ユーザモデル(User)から、idが1(find.(1))のものを取得
こうすればtaroさんのインスタンス(すぐに使用できるデータ)が取得できます。
挙動は
2.5.3 :001 > user1 = User.find(1)
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "taro", age: 23, created_at: "2020-03-31 02:27:04", updated_at: "2020-03-31 02:27:11">
このように流れてきます。
そしてこのようにすればidが1(taroさん)のageだけを取り出すことができます。
2.5.3 :002 > user1.age
=> "23"
#find_byとは
- id以外のカラムを指定して、1つのデータを取得する方法(idでも検索可能)
- id以外の値が分かっているときに使用できる
- 複数の条件指定が可能
- 値として返ってくるのは、条件にヒットした最初の1件のみ
- 検索の方法は モデル名.find_by(カラム名: 値) 例:User.find_by(name: "taro")
####使用方法
例えばUserモデルにあるjiroさんのデータが欲しいとします。
その場合、find_byで検索するとなると カラム名: 値 で検索して上げる必要があります。
Userモデル
id | name | age |
---|---|---|
1 | taro | 23 |
2 | jiro | 20 |
3 | sabu | 18 |
User.find_by(name: 'jiro')
→ユーザモデル(User)から名前がjiro(name: 'jiro')のデータを取得
と言う風になります。こうすればnameがjiroさんのデータを取り出すことができます。
挙動は
2.5.3 :001 > user = User.find_by(name: 'jiro')
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "jiro"], ["LIMIT", 1]]
=> #<User id: 2, name: "jiro", age: 20, created_at: "2020-03-31 02:27:26", updated_at: "2020-03-31 02:27:26">
このように流れてきます。そして、find_byでは 値として返ってくるのは条件にヒットした最初の1件のみ が返ってきます。
どういうことかと言うと
年齢が20才の2人がいたとします。
Userモデル
id | name | age |
---|---|---|
1 | taro | 23 |
2 | jiro | 20 |
3 | sabu | 20 |
このような場合にfind_byを使用して User.find_by(age: 20) としても sabuさんのデータは取れません。
2.5.3 :001 > user = User.find_by(age: 20)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."age" = ? LIMIT ? [["age", 20], ["LIMIT", 1]]
=> #<User id: 2, name: "jiro", age: 20, created_at: "2020-03-31 02:27:26", updated_at: "2020-03-31 02:27:26">
idを順にみていくので、ageが20である最初のデータはidが2のjiroさんになってしまいます。なので、sabuさんのデータを取ろうと思うと、別の条件でとるしかないということになります。
また、 複数の条件指定が可能 というのはこのようにします。
例えば、兵庫県出身の20才のデータを取得したい時には
Userモデル
id | name | age | pref |
---|---|---|---|
1 | taro | 23 | 大阪 |
2 | jiro | 20 | 東京 |
3 | sabu | 20 | 兵庫 |
2.5.3 :002 > user = User.find_by(age: 20, pref: '兵庫')
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."pref" = ? AND "users"."pref" = ? LIMIT ? [["age", 20], ["pref", "兵庫"], ["LIMIT", 1]]
=> #<User id: 3, name: "sabu", age: 20, pref: "兵庫", created_at: "2020-03-31 02:27:35", updated_at: "2020-03-31 03:49:24">
このようにすれば、複数条件に当てはまる最初のデータが返ってきます。
また、find_byで取り出したデータもインスタンスなので、このようにすれば指定のカラムのデータを取得することができます。
2.5.3 :003 > user.name
=> "sabu"
#データが見つからなかった時の違い
###findの場合
例えば下のようなUserモデルがあったとして、間違えて User.find(4)と存在しないidを指定したとします。
Userモデル
id | name | age |
---|---|---|
1 | taro | 23 |
2 | jiro | 20 |
3 | sabu | 20 |
2.5.3 :004 > user = User.find(4)
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 4], ["LIMIT", 1]]
Traceback (most recent call last):
1: from (irb):4
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=4)
このように返ってきます。
ActiveRecord::RecordNotFound (Couldn't find User with 'id'=4)
ここでは、idが4のデータは見つかりませんでした。といった エラー が返ってきます。エラーが返ってくるとエラー画面が表示され、動かなくなってしまいます。
####find_byの場合
同じUserモデルを使用して 間違えて User.find_by(name: 'gonta') と存在しないnameを指定したとします。
2.5.3 :005 > user = User.find_by(name: 'gonta')
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? LIMIT ? [["name", "gonta"], ["LIMIT", 1]]
=> nil
このように エラー ではなく nil が返ってきます。
nilが返ってくるということは、エラー画面は表示されずに処理が進みます。
####要するにどういうことか
例えばこのようなfindを使ったif文を書いたとします。
user = User.find(4)
if user
puts 'ユーザが見つかりました。'
else
put 'ユーザが見つかりませんでした。'
end
この場合、userには何も代入されておらず、エラー画面が表示されて動きません。
しかし、find_byを使ったif文にすると
user = User.find_by(id: 4)
if user
puts 'ユーザが見つかりました。'
else
put 'ユーザが見つかりませんでした。'
end
この場合には、userにはnilが代入されていることになり、if文のelseが適応となって ユーザが見つかりませんでした と出力されることになります。
#まとめ
findとfind_byの違いってサービスを開発してみるまでは、正直意味が分かりませんでした。
違いをしっかり理解して使っていくようにしましょう。
最後まで読んでいただきありがとうございました。
#参考にした記事
find、find_by、whereの違い
【Rails初心者必見!】ひたすら丁寧にデータ取得を説明(find, where)
大変参考になりました。ありがとうございます。