RubyとRailsの?系メソッドのまとめ

メソッド名の末尾に?が付くメソッド(勝手に?系メソッドと呼びます)がたくさんありすぎてよく分からなくなったのでまとめました。

Ruby

Rubyのメソッド。true/falseを返します。

  • nil?: オブジェクトがnilか?
  • empty?: インスタンス(配列、ハッシュ、文字列等)が空か?
  • include?: インスタンス(配列、ハッシュ、文字列等)に特定の値が含まれているか?
# nil?
> nil.nil?
=> true
> ''.nil?
=> false
> [].nil?
=> false

# empty?
> [].empty?
=> true
> {}.empty?
=> true
> ''.empty?
=> true
> ' '.empty?
=> false
> nil.empty?
=> NoMethodError

# include?
> [1,2,3].include?(2)
=> true
'abc'.include?('b')
=> true

Object#nil? (Ruby 3.2 リファレンスマニュアル)

String#empty? (Ruby 3.2 リファレンスマニュアル)

Array#include? (Ruby 3.2 リファレンスマニュアル)

Rails

Railsのメソッド。true/falseを返します。

  • blank?: インスタンス(配列、ハッシュ、文字列等)がnil、空か?(nil? + empty?)
  • present?: !brank?(brank? の反対)
# blank?
> nil.blank?
=> true
> [].blank?
=> true
> {}.blank?
=> true
> ''.blank?
=> true
> ' '.blank?
=> true

# present?
> nil.present?
=> false
> [].present?
=> false
> {}.present?
=> false
> ''.present?
=> false
> ' '.present?
=> false

真偽判定 | Railsドキュメント

バリデーション

Railsのバリデーションのチェックで使用します。true/falseを返します。

  • valid?: バリデーションがパスするか?
  • invalid?: !valid?(valid?の反対)

savecreate メソッド実行時に行われるバリデーション処理のみを実行するイメージ。

  • バリデーションエラーの場合はerrorsオブジェクトにエラーが入る
  • エラーはインスタンス.errors.full_messages で取得できる
# valid?
* class Book < ApplicationRecord
*   validates :title, presence: true
> end
=> {:presence=>true}

> Book.new(title: nil).valid?
=> false
> Book.new(title: 'book_name').valid?
=> true

# invalid?
Book.new(title: nil).invalid?
=> true
> Book.new(title: 'book_name').invalid?
=> false

Active Record バリデーション - Railsガイド

ActiveRecord

RailsActiveRecordで使えるメソッドです。

  • exists?
  • persisted?

exists?

レコードを存在確認します。true/falseを返します。

  • 引数に該当した時点で検索は終了する。
  • 全件取得するpresent? よりパフォーマンスが高い。
  • IN句検索: 条件のカラムの値を配列で複数指定する。どちらかにマッチすればtrueを返す。
  • AND句検索: 条件のカラムを複数指定する。両方にマッチすればtrueを返す。
# exists?
> User.exists?(51) # idで検索
  User Exists? (0.3ms)  SELECT 1 AS one FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 51], ["LIMIT", 1]]
=> true
> User.exists?(name: nil)
  User Exists? (0.3ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" IS NULL LIMIT ?  [["LIMIT", 1]]
=> false
> User.exists?(name: 'karlley')
  User Exists? (0.3ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "karlley"], ["LIMIT", 1]]
=> true

# exists? とpresent? のSQLの比較
> User.where(name: 'karlley').exists? # EXISTS?句で検索
  User Exists? (1.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "karlley"], ["LIMIT", 1]]
=> true
> User.where(name: 'karlley').present? # WHERE句で検索
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."name" = ?  [["name", "karlley"]]
=> true

# カラムの値を複数指定して検索(IN句で検索)
> User.exists?(id: [1,2])
  User Exists? (0.3ms)  SELECT 1 AS one FROM "users" WHERE "users"."id" IN (?, ?) LIMIT ?  [["id", 1], ["id", 2], ["LIMIT", 1]]
=> true
> User.exists?(id: [1,nil])
  User Exists? (0.4ms)  SELECT 1 AS one FROM "users" WHERE ("users"."id" = ? OR "users"."id" IS NULL) LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> true

# カラムを複数指定して検索(AND句)
> User.exists?(name: 'karlley', id: 51)
  User Exists? (0.3ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = ? AND "users"."id" = ? LIMIT ?  [["name", "karlley"], ["id", 51], ["LIMIT", 1]]
=> true
> User.exists?(name: 'karlley', id: nil)
  User Exists? (0.3ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = ? AND "users"."id" IS NULL LIMIT ?  [["name", "karlley"], ["LIMIT", 1]]
=> false

Active Record クエリインターフェイス - Railsガイド

ActiveRecordでは present? の代わりに exists? を使おう - Qiita

exists? とpresent? の使い分け

レコードの存在チェックを行った後にインスタンスを使って何か処理をする場合はexists?メソッドではなくpresent?メソッドを使います。

exists?メソッドは...存在チェックの後にインスタンスを使う必要がなく、レコードの存在チェックだけを行う場合に使用します。

【Rails】 exists?メソッドの使い方~present?との違い | Pikawaka

返り値のオブジェクトを使って処理を行う/行わないで使い分けます。

# exists? はインスタンスに対して呼び出せない
> user = User.find_by(name: 'karlley')
> user.present?
=> true
> user.exists?
=> NoMethodError # インスタンスに対して呼び出せない

# インスタンスを使って処理を行う: present?
> user = User.find_by(name: 'karlley')
* if user.present?
*   puts "#{user.name}のレコードは存在します。"
* else
*   puts "#{user.name}のレコードは存在しません。"
> end
karlleyのレコードは存在します。
=> nil

# インスタンスを使って処理を行わない: exists?
* if User.exists?(name: 'karlley')
*   puts "レコードは存在します。"
* else
*   puts "レコードは存在しません。"
> end
  User Exists? (0.4ms)  SELECT 1 AS one FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "karlley"], ["LIMIT", 1]] # SQLが発行される
レコードは存在します。
=> nil

persisted?

レコードが保存済みなのかを確認します。true/falseを返します。

> user = User.new # saveしていない
> user.persisted?
=> false
> user = User.first # 既存レコード
> user.persisted?
=> true

【Rails】DBに保存済みかどうかをチェックするpersisted?メソッドについて簡単に解説するよ|TechTechMedia

まとめ

頻出する?系メソッドだけですが情報を整理できてスッキリしました。 まだまだたくさんありそうなので見つけたら追記していこうと思います。

参照

Object#nil? (Ruby 3.2 リファレンスマニュアル)

String#empty? (Ruby 3.2 リファレンスマニュアル)

Array#include? (Ruby 3.2 リファレンスマニュアル)

真偽判定 | Railsドキュメント

Active Record バリデーション - Railsガイド

Active Record クエリインターフェイス - Railsガイド

ActiveRecordでは present? の代わりに exists? を使おう - Qiita

【Rails】 exists?メソッドの使い方~present?との違い | Pikawaka

【Rails】DBに保存済みかどうかをチェックするpersisted?メソッドについて簡単に解説するよ|TechTechMedia