1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails初学者】バリデーションの基礎についてざっくり理解する -Part2(各種バリデータの詳細)

Last updated at Posted at 2025-12-13

Part1 続き

前回の記事では、Railsのバリデーションのおおまかな概要についてまとめました📘
今回は具体的なバリデータについてまとめていきたいと思います!

validation-flow2.png

バリデーションの種類

ここからは実際にコードにどのようにバリデーションを記述するかまとめていきます!

先に今回紹介するバリデーションを一覧しました✍️

バリデーション名 説明
presence 属性が空でないことを検証
absence 属性が空であることを検証
uniqueness 属性の値がユニークであることを検証
inclusion 属性の値が特定のセットに含まれていることを検証
exclusion 属性の値が特定のセットに含まれていないことを検証
acceptance 利用規約などのチェックボックスにチェックが入っていることを検証

バリデーションの定義方法

ActiveRecordでは自分でバリデーションのルールを書かずとも、すでに多数のバリデーションが用意されているので、まずそれらについて確認していきます!

ActiveModelにて提供されているvalidatesメソッドを使用して、モデルクラス内でバリデーションを定義します。

validates :属性名, バリデーションの種類: オプション

presence

指定した属性が「空でない」ことを検証するバリデーションです。最もよく使われるバリデーションの1つです⭐️

class Book < ApplicationRecord
  validates :title, presence: true
end

この場合titleが空であればエラーになり、エラーメッセージは「Title can't be blank」となります。

関連付けが存在することを確認したい場合、外部キーが存在するのかどうかを検証するのではなく、関連付けられたオブジェクト自体が存在するかどうかを検証します。

class Book < ApplicationRecord
  # ❌ 間違い: author_idが存在するか検証
  validates :author_id, presence: true

  # ⭕ 正しい: authorオブジェクトが存在するか検証
  belongs_to :author
  validates :author, presence: true
end

またboolean型の属性に対して、存在を検証する場合は注意が必要です!
同じようにpresence: trueを使用すると、falseの場合にエラーとなってしまいます😥
falseも有効な値として扱いため、inclusionまたはexclusionを使用して検証する必要があります。

Class Book < ApplicationRecord
  # ❌ 間違い: falseの場合にエラーになる
  validates :published, presence: true

  # ⭕ 正しい: trueまたはfalseを許可
  validates :published, inclusion: [true, false]
  # または
  validates :published, exclusion: [nil]
end

空でないことをどうやってチェックしているの?

presenceバリデータの内部では、Object#blank?メソッドを使用して、属性の値が空であるかどうかを判断しています。
具体的には、以下の条件で空とみなされます。

  • nilである
  • 空の文字列(""
  • スペース、タブ、改行の空白のみの文字列(" "
  • 空の配列([]
  • 空のハッシュ({}

absence

presenceバリデータの逆の動作をします。指定した属性が「空である」ことを検証します。また検証内容の性質上、ifオプションと組み合わせた条件付きバリデーションで使用される場面が多いです。

class Book < ApplicationRecord
  validates :coupon_code, absence: true, if: :gest_user?
end

この場合、gest_user?メソッドがtrueを返す場合にのみ、coupon_codeが空であることを検証します。エラーメッセージは「Coupon code must be blank」となります。

空であることのチェックは、Object#present?メソッドを使用して行われます!

uniqueness

属性の値が一意(ユニーク)であり他のレコードと重複していないことを検証します。メールアドレスやユーザー名など、重複を許さない属性に対してよく使用されます。

class User < ApplicationRecord
  validates :email, uniqueness: true
end

この場合、emailが他のレコードと重複している場合にエラーとなり、エラーメッセージは「Email has already been taken」となります。

データベースレベルのユニーク制約も必要

  • uniquenessバリデーションはアプリケーションレベルでの検証であり、同時に複数のリクエストが来た場合などに重複レコードが作成される可能性があります😱
  • この現象をレースコンディションと言うらしいです💦
  • そのため、データベースレベルでもユニーク制約を設定することがベストプラクティスとされています!

scopeオプション

特定のカラムの組み合わせで一意性を検証したい場合は、scopeオプションを使用します。

class Employee < ApplicationRecord
  validates :email, uniqueness: { scope: :organization_id }
end

この場合、同じorganization_id(組織)内でemailが一意であることを検証します。

複数カラムの組み合わせで一意性を検証したい場合は、scopeオプションに配列を渡します。

class Employee < ApplicationRecord
  validates :email, uniqueness: { scope: [:organization_id, :department_id] }
end

この場合、同じorganization_id(組織)かつdepartment_id(部署)内でemailが一意であることを検証します。

case_sensitiveオプション

デフォルトではuniquenessバリデーションは大文字と小文字を区別しますが、case_sensitive: falseオプションを指定することで、大文字と小文字を区別せずに検証することができます。

class User < ApplicationRecord
  validates :username, uniqueness: { case_sensitive: false }
end

conditionsオプション

特定の条件に基づいて一意性を検証したい場合は、conditionsオプションを使用します。
SQLのWHERE句に相当する条件を指定できます。

class Article < ApplicationRecord
  validates :title, uniqueness: { conditions: -> { where(status: 'published') }
  }
end

この場合、statuspublishedのレコードに対してのみtitleの一意性を検証します。

inclusionexclusion

これらのバリデータは、属性の値が特定のセットに「含まれているか」「含まれていないか」をチェックします。
指定するセットには、任意のenumerableオブジェクト(配列やrangeproclambdaやシンボルで動的に生成されたコレクションなど)を利用できます。
参考:Railsガイド バリデーションの使い方より

このように、自分でセットを指定して、その中に含まれているか確認したいときはinclusion、含まれていないかを検証したいときはexclusionを使用します。

class User < ApplicationRecord
  validates :age, inclusion: { in: 18..65 }
  validates :username, exclusion: { in: %w[admin root superuser] }
end

この場合、ageが18から65の範囲内であることを検証し、usernameadminrootsuperuserのいずれかでないことを検証します。
inオプションで値のセットが渡せれるようになっています。

acceptance

ユーザーがチェックボックスにチェック✅を入れたかどうかを検証するバリデーションです。
利用規約への同意やプライバシーポリシーの確認など、ユーザーの明示的な同意が必要な場面で使用します。

class User < ApplicationRecord
  validates :terms_of_service, acceptance: true
end

この場合、terms_of_service属性がtrueであることを検証します。エラーメッセージは「Terms of service must be accepted」となります。

このバリデータの特徴としては、データベースにカラムが存在しなくても動作する点です。
具体的にはフォームから送信された値だけを検証し、データベースには保存されません。

acceptanceオプション

acceptanceオプションを使用して、受け入れ可能な値をカスタマイズできます。デフォルトでは[1, true]が受け入れ可能な値ですが、他の値も指定できます。

class User < ApplicationRecord
  validates :terms_of_service, acceptance: { accept: ['yes', 'YES', 'Y'] }
end

この場合、terms_of_service属性が'yes''YES'、または'Y'であることを検証します。

Part3へ続く

参考記事

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?