🐘
【Rails】present? exists? presence の違い
概要
「条件に合致するレコードが存在するかどうか」というコードを書くことはよくあるはず。
そんなとき present?
を使用するのか exists?
を使用するのか、はたまた presence
を使用するのかという選択肢がある。
それぞれどんな感じで動いているのか、どんなときに使うのかというのを書いていく。
環境
rails (7.0.8)
RUBY VERSION
ruby 3.1.2p20
present?
rails console
> Article.where(title: "あああ").present?
SELECT `articles`.* FROM `articles` WHERE `articles`.`title` = 'あああ'
=> true
present?
は SQL で データベースから title が「あああ」である全レコードを取得し、
Rails(ActiveSupport) のコードで存在を確認している。
exists?
rails console
> Article.where(title: "あああ").exists?
SELECT 1 AS one FROM `articles` WHERE `articles`.`title` = 'あああ' LIMIT 1
=> true
exist?
は title が「あああ」のレコードを1件だけ取得し、「1」という固定値を返している。
present?
のようにレコードを全件取得せず、存在の有無だけを確認している。
レコード有無のチェックでいうと、present?
よりもパフォーマンスが良い。
presence
rails console
> Article.where(title: "あああ").presence
SELECT `articles`.* FROM `articles` WHERE `articles`.`title` = 'あああ'
=> [#<Article:0x0000ffffae21c470 id: 1, title: "あああ", body: "body", is_published: false, created_at: Mon, 26 Feb 2024 00:52:53.492071000 UTC +00:00, updated_at: Mon, 26 Feb 2024 00:52:53.492546000 UTC +00:00>]
rails console
> Article.where(title: "ををを").presence
Article Load (6.3ms) SELECT `articles`.* FROM `articles` WHERE `articles`.`title` = 'ををを'
=> nil
presence
は発行されるクエリはpresent?
と同じですが、戻り値として、該当するデータセットを返す。
該当するレコードが存在しない場合、nil を返す。
レコードの存在確認ではなく、「値が存在すればその値を使い、なければ別の値を使う」のようなコードを書きたいときに便利。
> user.name || "名前がありません"
=> "たなか"
> user.name = nil
> user.name || "名前がありません"
=> "名前がありません"
まとめ
SQL | 戻り値 | ユースケース | |
---|---|---|---|
present? | 条件に当てはまるコードを全件取得。その後あるかどうか | true / false | 単純な Ruby のコードでの存在確認 |
exists? | 条件に当てはまるコードが存在するかどうか | true / false | テーブルに条件に一致するレコードの存在確認 |
presence | present? と同じ | 該当するデータセット / nil | 値が存在すればその値を使う。なければ別の値を使う |
Discussion