スポンサーリンク
find
findメソッドはテーブルの中からidを指定してモデルを取得したい場合に使います。
引数に渡せるのはidあるいは、idの配列。
1 2 3 4 5 | # idが1番のuserを取得 user = User.find 1 # idが2番と3番のuserを取得 users = User.find [2, 3] |
idを1つだけ指定した場合は戻り値はモデルオブジェクトであるのに対して、idを配列で渡した場合は戻り値は配列(モデルオブジェクトの配列)になるので注意。
1 2 3 4 5 6 7 8 | # idが1番のuserを取得 user = User.find 1 user.name # idが2番と3番のuserを取得 users = User.find [2, 3] users[0].name users[1].name |
もし指定したidのモデルが存在しなければArgumentError(例外)が投げられるので注意が必要です。
スポンサーリンク
find_by
find_byメソッドは、条件を指定してモデルを1件だけ取得したい場合に使います。
引数には連想配列を渡します。
1 2 3 4 5 6 7 8 | # idが1番のuserを1件取得 user = User.find_by id: 1 #nameが"nobuo"のuserを1件取得 user = User.find_by name: "nobuo" #nameが"nobuo"かつ、addressが"tokyo"のuserを1件取得 user = User.find_by name: "nobuo", address: "tokyo" |
find_byメソッドで取得できるのは1件のみです。もし条件に合うモデルが複数あった場合は最新の1件が取得されます。
もし指定したモデルが見つからない場合は戻り値はnilになります。
where
whereは条件に合うモデルを複数取得したい場合に使います。
引数には連想配列を渡します。
1 2 3 4 5 | # addressが"tokyo"のuserを全て取得 users = User.where address: "tokyo" # addressが"tokyo"かつ、jobが"engineer"のuserを全て取得 users = User.where address: "tokyo", job: "engineer" |
戻り値はActiveRecord::Relationというオブジェクトです。ActiveRecord::Relationというのは簡単に言えばモデルの配列なのですが、単なる配列ではありません。
whereメソッドは戻り値がActiveRecord::Relationであるおかげで、非常に便利な使い方ができます。チェーンメソッド形式でさらに条件を絞り込むような使い方ができるんです。
1 2 | # addressが"tokyo"のuserの内、jobが"engineer"のuserを全て取得 users = User.where(address: "tokyo").where(job: "engineer") |
先程の例でもありましたが、こう書いても結果は同じです。↓
1 2 | # addressが"tokyo"かつ、jobが"engineer"のuserを全て取得 users = User.where address: "tokyo", job: "engineer" |
条件に合致したうちの5件だけ取得したい場合にはlimitメソッドを使って以下のように書けます。
1 2 | # addressが"tokyo"のuserの内、最新の5件を取得 users = User.where(address: "tokyo").limit 5 |
こういったチェーンメソッドを上手く使えば、処理の中でかなり柔軟にクエリを書くことができると思います。
whereメソッドのもう一つ便利な使い方は、SQL文のwhere句をそのまま引数に渡して使うことができる点です。
1 2 3 4 5 | # titleに"プログラミング"が含まれるpostを全て取得 posts = Post.where("title like ?", "プログラミング") # titleに"プログラミング"が含まれるか、あるいはcontentに"rails"が含まれるpostを全て取得 posts = Post.where("(title like ?) or (content like ?)", "プログラミング", "rails") |
動的なパラメータを指定する時は、?を使ってインジェクション対策をした方がいいです。
もちろん、この場合も戻り値はActiveRecord::Relationなので、さらにメソッドをつなげて絞り込むことが可能です。
ちなみに条件に合うモデルが1件だけだったとしても戻り値はモデル自体ではなく、ActiveRecord::Relationになります。要素数が1つの配列みたいなものです。
なので、whereメソッドで取得したデータを出力する際は、必ずeachメソッド等で回す必要があります。
合致しなかった際の戻り値
whereメソッドで条件検索した結果、条件に合致するモデルが無かった場合の処理には注意が必要です。
1つも合致するモデルが無かった場合も、戻り値はActiveRecord::Relationオブジェクトになります。中身が空っぽ(要素0個)のActiveRecord::Relationオブジェクトです。
なのでif文の条件に使う際は必ずpresent?メソッドで中身を確かめましょう。
1 2 3 4 5 6 7 8 9 10 11 | # 間違い↓ post = Post.where(title: "Ruby on Rails") if post #postが空っぽでも実行される end # 正解↓ post = Post.where(title: "Ruby on Rails") if post.present? #postが1件以上あれば実行される end |
all
全てのモデルを取得したい場合に使います。
引数は取りません。
1 2 | # 全てのuserを取得 users = User.all |
これは説明するまでもないかと思いますが、とにかく全部欲しい場合はこれです。
使い分け
findメソッドはもしそのidのモデルが見つからなかった場合(削除されていた等)、いちいち例外を吐いて止まることになるので、個人的には使いません。find_byメソッドの方が使い勝手がいいです。
1 2 3 4 | user = User.find_by id: 1 if user #userが存在する場合の処理 end |
モデルを1件だけ取得したい場合はfind_byメソッド。複数取得してeach doで回したい場合はwhereを使うようにしたらいいと思います。
find_byで取得したオブジェクトをviewでeach doしてしまったら、エラーになるので、each doで出力する時は仮に1件しか要らない場合であっても絶対にwhereを使いましょう。
[…] 参考記事 […]
by Railsのランキング機能で得た知見 | IT技術情報局 2018年5月7日 11:52 PM
[…] find、find_by、where などモデルを取得する方法まとめ | Ruby on Rails 始めました […]
by クエリ [Rails] – Site-Builder.wiki 2019年5月21日 9:42 PM