おぴよの気まぐれ日記

おぴよの気まぐれ日記

岡山やプログラミング、ファッションのこと、子育てや人生、生き方についての備忘録。

【Rails】データが1件でもあるかどうかチェックするには`Model.exists?`

Ruby on Railsでデータベースにデータが存在するかどうかチェックしたい場合があると思います。

  • そもそもデータがあるかどうか知りたい時
  • ログインしたユーザーが管理者ユーザーがどうかをチェックしたい

そんな時はModel.exists?()を使いましょうって話です。

データが存在するかチェックする

> User.exists?
  User Exists (3.0ms)  SELECT  1 AS one FROM "users" LIMIT $1  [["LIMIT", 1]]
=> true

Userモデルにデータが1件でも存在するかのチェックです。

条件付きで存在をチェックする

> User.exists?(id: [1, 2, 3], name: 'opiyo', role: 'admin')
  User Exists (0.6ms)  SELECT  1 AS one FROM "users" WHERE "users"."id" IN ($1, $2, $3) AND "users"."name" = $4 AND "users"."role" = $5 LIMIT $6  [["id", 1], ["id", 2], ["id", 3], ["name", "opiyo"], ["role", "admin"], ["LIMIT", 1]]
=> false

Userモデルから管理者ユーザーを探すような条件を渡してます。条件は何個でもつけれますし、配列も渡せちゃいます。

find_byも同じ使い方出来るじゃね?

データを1件だけ取得するのに便利なのがModel.find_by()だと思うのですが、exists?と同じような使い方ができますね。

> User.find_by(id: [1, 2, 3], name: 'opiyo', role: 'admin')
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" IN ($1, $2, $3) AND "users"."name" = $4 AND "users"."role" = $5 LIMIT $6  [["id", 1], ["id", 2], ["id", 3], ["name", "opiyo"], ["role", "admin"], ["LIMIT", 1]]
=> nil

さっきのと全く同じ条件ですが戻り値が違いますね。今回はnilです。

取得できた場合はデータが1件取れますね。

> User.find_by(name: 'opiyo', role: 'admin')
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = $1 AND "users"."role" = $2 LIMIT $3  [["name", "opiyo"], ["role", "admin"], ["LIMIT", 1]]
=> #<User id: 175, created_at: "2018-05-28 02:59:58", updated_at: "2019-06-18 05:42:19", name: "opiyo", role: "admin">

データも欲しいけど存在チェックもしたいっていう贅沢な事をする場合は、こんな書き方で叶えることが出来るので便利!

> if user = User.find_by(name: 'opiyo', role: 'admin')
*   puts user.name
*   puts user.role
* end  
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = $1 AND "users"."role" = $2 LIMIT $3  [["name", "opiyo"], ["role", "admin"], ["LIMIT", 1]]
opiyo
admin

取得に失敗した場合はuser = nilになりますが、nilfalseなのでif文に入りません。

> if user = User.find_by(name: 'opiyoopiyo', role: 'admin')
*   puts user.name  
*   puts user.role  
* end  
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = $1 AND "users"."role" = $2 LIMIT $3  [["name", "opiyoopiyo"], ["role", "admin"], ["LIMIT", 1]]
=> nil

さっき出力された、opiyoadminが表示されませんね。

参考サイト

railsdoc.com