Rails5のfindとfind_byとfind_by!の使い分けメモ

「モデルからデータを取ってきたい!」

「えーっと、findとfind_byとfind_by!ってどれがどんな指定の仕方だっけ?」

どういう時にどっちを使えばいいんだっけ?みたいな事をよく覚えていなかった時に書いたメモです。

スポンサーリンク

環境情報

rails (5.0.0.1)
ruby 2.3.1p112

find

特定の”ID”のレコードを1つ探す

User.find(1)

カラムを指定してデータを引っ張ってくることは出来ない(idのみ)

[24] pry(main)> User.find(email:"example@exmaple.com")
  User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = NULL LIMIT 1
ActiveRecord::RecordNotFound: Couldn't find User with 'id'={:email=>"example@example.com"}

複数の値を渡すこともできる(idが1と2)

User.find(1,2)

なお、指定したデータが一つでも存在しなかった場合はデータが取得できない

(下記の例はid:1は存在するがid:3は存在しない場合)

[19] pry(main)> moge = User.find(1,3)
  User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 3)
ActiveRecord::RecordNotFound: Couldn't find all Users with 'id': (1, 3) (found 1 results, but was looking for 2)

find_by

指定したカラムが特定の値を持つレコードを1つ探す。

 User.find_by(email:"example@exmaple.com")

何もヒットしなければ nil になる

[37] pry(main)> User.find_by(email:"nodata@example.com")
  User Load (0.6ms)  SELECT  `users`.* FROM `users` WHERE `users`.`email` = 'nodata@example.com' LIMIT 1
=> nil

カラム名の指定をしないとエラーになる

[36] pry(main)> User.find_by("example")
  User Load (2.0ms)  SELECT  `users`.* FROM `users` WHERE (example) LIMIT 1
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'example' in 'where clause': SELECT  `users`.* FROM `users` WHERE (example) LIMIT 1

複数のデータを取得することは出来ない。

[36] pry(main)> User.find_by(email:"example@example.com", "exmaple2@example.com")
SyntaxError: unexpected ')', expecting =>

find_by!

findを使って何もヒットしなかった場合

例外(ActiveRecord::RecordNotFound)が発生する。

find_byを使って何もヒットしなかった場合

nilが返る(例外は発生しない)

find_byを使っても例外を発生させたい場合

しかし、find_byを使った場合でも例外を発生させたい場合がある。
そんな時にfind_by!を使う。find_byに「!」を付けるだけ

[38] pry(main)> User.find_by(email:"nodata@example.com")
  User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`email` = 'nodata@example.com' LIMIT 1
=> nil
[39] pry(main)> User.find_by!(email:"nodata@example.com")
  User Load (0.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`email` = 'nodata@example.com' LIMIT 1
ActiveRecord::RecordNotFound: Couldn't find User

上記のように何もヒットしなくても例外が発生しているのが分かる。