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?

More than 3 years have passed since last update.

findとfind_byの違いを初心者がまとめてみました。

Last updated at Posted at 2020-03-31

この記事ではfindfind_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の違いってサービスを開発してみるまでは、正直意味が分かりませんでした。
違いをしっかり理解して使っていくようにしましょう。
最後まで読んでいただきありがとうございました。:relaxed:

#参考にした記事
find、find_by、whereの違い
【Rails初心者必見!】ひたすら丁寧にデータ取得を説明(find, 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?