1. present?
- Railsのメソッド
- オブジェクトがある場合はtrueを返す
- present?の反対は、blank?
- 実行するとキャッシュされる
発行されるクエリを見てみると、1回全部の該当レコードをごそっと取ってきていることが分かる
SELECT "articles".* FROM "articles" WHERE "articles"."title" = ? [["title", "Test"]]
irb(main):001:0> Article.where(title: 'Test').present?
(1.6ms) SELECT sqlite_version(*)
Article Load (0.2ms) SELECT "articles".* FROM "articles" WHERE "articles"."title" = ? [["title", "Test"]]
=> true
2. exists?
- Railsのメソッド
- SQLのexists式を使う
- 該当レコードが1件でもあればtrueを返す
発行されるクエリを見てみると、該当するレコードをLIMIT 1で絞り込んでいることが分かる
SELECT 1 AS one FROM "articles" WHERE "articles"."title" = ? LIMIT ? [["title", "Test"], ["LIMIT", 1]]
irb(main):002:0> Article.where(title: 'Test').exists?
Article Exists? (0.2ms) SELECT 1 AS one FROM "articles" WHERE "articles"."title" = ? LIMIT ? [["title", "Test"], ["LIMIT", 1]]
=> true
3. exists?を使うべき時
- 該当のレコード数が何百万件と多い時
- present?の場合該当する全レコードを取得するため、データが多い場合そこでパフォーマンスの問題が生じる可能性が高い
- キャッシュを使う必要がない時
if Article.where(title: 'Test').exists?
p 'タイトルがTestという記事が存在します!'
else
p 'タイトルがTestという記事は存在しません'
end
Article Exists? (0.2ms) SELECT 1 AS one FROM "articles" WHERE "articles"."title" = ? LIMIT ? [["title", "Test"], ["LIMIT", 1]]
"タイトルがTestという記事が存在します!"
=> "タイトルがTestという記事が存在します!"
4. present?を使うべき時
- 存在確認後に、キャッシュを使う予定がある時
- 既にキャッシュが存在していて、それが使える時
articles.present?
でArticle.where(id: 1)
の結果がキャッシュされ、articles.pluck(:title)
実行時にはキャッシュを使うため、クエリは1回しか発行されない
articles = Article.where(id: 1)
if articles.present?
p "タイトルは#{articles.pluck(:title)}です"
else
p '該当する記事がありません'
end
Article Load (0.2ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? [["id", 1]]
"タイトルは[\"Test\"]です"
=> "タイトルは[\"Test\"]です
exists?を使うと、クエリが2回発行されてしまう
if articles.exists?
p "タイトルは#{articles.pluck(:title)}です"
else
p '該当する記事がありません'
end
Article Exists? (0.2ms) SELECT 1 AS one FROM "articles" WHERE "articles"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
(0.1ms) SELECT "articles"."title" FROM "articles" WHERE "articles"."id" = ? [["id", 1]]
"タイトルは[\"Test\"]です"
=> "タイトルは[\"Test\"]です"
5. まとめ
present?とexists?を使う基準は以下の通り
- exists?:キャッシュを使わない、該当のレコード数が何百万件と多い時
- present?:存在確認後にキャッシュを使う、存在確認前に既にキャッシュがある時
参考