【Rails】バリデーション(Validation)の種類と使い方総まとめ!

目次

バリデーションとは?

バリデーションとは、Active Recordモデルに対して、データの検証を行う機能です。

データベースに保存する前にユーザーが入力したデータを検証し、不正な値がある場合にはエラーメッセージを表示します。

Active Recordモデルでバリデーションを定義するにはvalidatesメソッドを使用します。
このメソッドは、モデルの属性に対して検証ルールを設定するためのオプションを受け取ります。

基本的な書き方

バリデーションはvalidatesにカラム名と検証ルールを指定して記述します。

基本的な書き方を以下に示します。

validates :カラム名, 検証ルール

バリデーションの種類

Railsで利用可能な主要なバリデーションの種類を一覧を示します。

種類内容
presence値が存在しているか検証する。空文字やnilの場合にエラーとなる。
absence値が存在しないことを検証する。存在している場合にエラーとなる。
uniqueness一意性の検証をする。重複している値がある場合にエラーとなる。
numericality数値を検証する。指定された条件に合わない場合にエラーとなる。
length文字列の長を検証する。指定された条件に合わない場合にエラーとなる。
formatフォーマットを検証する。正規表現を指定して、指定されたパターンに合わない場合にエラーとなる。
inclusion値が含まれているか検証する。指定された値が含まれていない場合にエラーとなる。
exclusion値が含まれていないか検証する。指定された値が含まれている場合にエラーとなる。
confirmation2つの値が完全に一致しているか検証する。パスワードの確認などに使用する。
acceptanceチェックボックスにチェックされているか検証する。チェックボックスがチェックされていない場合にエラーとなる。
validates_associated関連先のバリデーションを検証する。関連先のバリデーションに問題がある場合にエラーとなる。
validates_with独自で作成したカスタムバリデーションを使用する。
validates_each1つのブロックに対して属性を検証する。

presenceの使い方

presenceバリデーションは指定された値が存在することを検証します。

指定された属性がnilまたは空の場合にエラーを発生させます。

例えば、Userモデルにname属性がある場合、以下のようにバリデーションを追加します。

class User < ApplicationRecord
  validates :name, presence: true
end

上記の例ではUserモデルのname属性にpresence: trueを追加することで、name属性が存在することを検証しています。

つまり、name属性は空にしてはいけません。
name属性が空の場合バリデーションエラーが発生しデータベースには保存されません。

また、presenceバリデーションは外部キーの存在を検証するときにも使用できます。
以下はPostモデルでuser_id属性にpresenceバリデーションを使用する例です。

class Post < ApplicationRecord
  belongs_to :user
  validates :user_id, presence: true
end

上記の例ではPostモデルがUserモデルに属しており、user_idカラムにpresenceバリデーションが設定されています。
これによりPostモデルのレコードが作成される前にuser_idカラムが空でないことを検証することができます。

Postモデルのレコードを作成する前に関連するUserモデルのレコードが作成されていることを検証することができます。

これらの例からも分かるようにpresenceバリデーションは、モデルに存在する属性や関連の存在を確認するために非常に便利なバリデーションです。
必須フィールドや外部キーの存在を検証するときはpresenceバリデーションを積極的に使用すると安全性を高めることができます。

absenceの使い方

absenceバリデーションは特定の値が存在しないことを検証します。
presenceバリデーションとは対照的に値が存在しないときにバリデーションを通過します。

以下はUserモデルでname属性が存在しないことを検証する例です。

class User < ApplicationRecord
  validates :name, absence: true
end

name属性に何らかの値が設定されている場合はバリデーションエラーが発生します。
name属性が空でなければバリデーションを通過しません。

uniquenessの使い方

uniquenessバリデーションは、値が一意であることを検証します。

同じ値を持つレコードを複数存在させたくないときなどによく使われます。

以下はUserモデルでemail属性が一意であることを検証する例です。

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

既にemailカラムに同じ値が存在しているときはバリデーションエラーが発生します。

また、scopeオプションを使用して、一意性を検証する範囲を限定する事もできます。

例えば、同じteam_idの値を持つレコードの範囲で、usernameの値が一意であることを検証する場合は以下のようになります。

class User < ApplicationRecord
  validates :username, uniqueness: { scope: :team_id }
end

上記の例ではusernameカラムとteam_idカラムの値の組み合わせが一意であることを検証しています。

これによりusernameの値が同じteam_idカラムを持つ複数のレコードに存在しないことを検証できます。

numericalityの使い方

numericalityバリデーションは、値が数値であることを検証します。

属性の値が整数または浮動小数点数であることを検証できます。

以下は、Productモデルでprice属性が数値であることを検証する例です。

class Product < ApplicationRecord
  validates :price, numericality: true
end

もし、priceカラムの値が数値でない場合はバリデーションエラーが発生します。

また、以下オプションで値に制約を付けることができます。

オプション説明
only_integertrueの場合は整数でなければならない。
greater_than指定の値よりも大きくなければならない。
greater_than_or_equal_to指定の値と等しいか、それよりも大きくなければならない。
equal_to指定の値と等しくなければならない。
less_than指定の値よりも小さくなければならない。
less_than_or_equal_to指定の値と等しいか、それよりも小さくなければならない。
other_than指定の値以外の値でなければならない。
in指定された範囲に値が含まれていなければならない。
oddtrueの場合は奇数でなければならない。
eventrueの場合は偶数でなければならない。

以下はProductモデルでprice属性が10以上であることを検証する例です。

class Product < ApplicationRecord
  validates :price, numericality: { greater_than_or_equal_to: 10 }
end

また、only_integerオプションを使用して、属性の値が整数であることを検証する例です。

class Product < ApplicationRecord
  validates :quantity, numericality: { only_integer: true }
end

これらのオプションを組み合わせて、より複雑な数値のバリデーションを行うこともできます。

numericalityバリデーションはデータの正確性を確保する上で非常に有用ですが、値が文字列である場合は適用されませんので注意しましょう。

lengthの使い方

lengthバリデーションは値が指定された文字数の範囲内にあることを検証します。

値が文字列または配列である場合は値の長さが指定された範囲内であることを検証します。
また値が数値である場合、数値の桁数が指定された範囲内であることを検証します。
属性がハッシュ(Hash)である場合はハッシュのサイズが指定された範囲内であることを検証します。

以下のオプションで長さを制限することができます。

オプション説明
minimum指定の値より小さな値にはできない。
maximum指定の値より大きな値にはできない。
in指定された範囲内の値でなければならない。
is指定の値と等しい値でなければならない。

例えば、Userモデルでnameカラムが2文字以上30文字以下であることを検証する場合、以下のようなバリデーションを定義できます。

class User < ApplicationRecord
  validates :name, length: { minimum: 2, maximum: 30 }
end

また、lengthバリデーションではinオプションを使用して、カラムの値が指定された範囲内にあることを検証することもできます。

例えば、以下のようにdescriptionカラムが100文字以上200文字以下であることを検証することができます。

class Product < ApplicationRecord
  validates :description, length: { in: 100..200 }
end

さらににisオプションを使用して、値の長さが指定された値に等しいことを検証することもできます。

例えば、以下のようにzipcodeカラムが7文字であることを検証することができます。

class Address < ApplicationRecord
  validates :zipcode, length: { is: 7 }
end

formatの使い方

formatバリデーションは、値が指定された正規表現と一致するかどうかを検証します。

例えば、メールアドレスの形式が正しいかどうかを検証する場合は、次のように書くことができます。

class User < ApplicationRecord
  validates :email, format: { with:/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i }
end

withoutオプションを使うと、指定された形式にマッチしない正規表現を検証することもできます。

inclusionの使い方

inclusionバリデーションは指定された値が含まれているかどうかを検証するバリデーションです。

例えば、性別を「男性」「女性」「その他」のいずれかに限定したい場合に使用できます。
以下は、性別を「男性」「女性」「その他」のいずれかに限定する例です。

class User < ApplicationRecord
  validates :gender, inclusion: { in: ['male', 'female', other'] }
end

値が配列に含まれている場合はバリデーションを通過し、含まれていない場合はバリデーションエラーが発生します。

exclusionの使い方

exclusionバリデーションは、指定された値が含まれていないかどうかを検証するバリデーションです。

例えば、パスワードに特定の文字列を含めたくない場合に使用できます。
以下は、パスワードに「password」と「admin」といった文字列を含めさせない例です。

class User < ApplicationRecord 
  validates :password, exclusion: { in: ['password', 'admin'] }
end

値が含まれている場合はバリデーションエラーが発生し、含まれていない場合はバリデーションを通過します。

入力値に特定のキーワードが含まれないようにする場合や、特定の値を除外したい場合など、exclusionバリデーションは値が特定の値や文字列を含まないようにする場合に便利です。

confirmationの使い方

confirmationバリデーションは、入力された値が同じかどうかを検証するバリデーションです。

通常はパスワードなどのフィールドに使用されます。
例えば、ユーザーがパスワードを入力し、同じパスワードを再度入力する必要がある場合に使用します。

class User < ApplicationRecord
  validates :password, confirmation: true
end

この例では、Userモデルのpasswordカラムにに対してconfirmationバリデーションを追加しています。

確認用のフィールドの名前は、確認したい属性名に「_confirmation」を追加したものになります。

<%= text_field :user, :password %>
<%= text_field :user, :password_confirmation %>

またcase_sensitiveオプションを用いて、大文字小文字を区別するか制限をすることができます。
デフォルトでは、このオプションはtrueになります。

class User < ApplicationRecord
  validates :password, confirmation: { case_sensitive: false }
end

confirmationバリデーションは、入力された値が一致するかどうかを確認するため、メールアドレスの確認などパスワード以外の任意の値に対しても使用することができます。

acceptanceの使い方

acceptanceバリデーションは、フォームなどでチェックボックスの入力を検証する際に使用されるバリデーションです。
このバリデーションを使用することで、チェックボックスがチェックされていることを検証できます。

利用規約の同意など何らかの文書に目を通したことを確認させる場合によく使われます。

acceptanceバリデーションを使用するには、モデルで以下のように定義します。

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

またacceptオプションを付けることで「同意済み(accepted)」とみなす値を指定できます
デフォルトは['1', true]となっています。

変更は以下のように簡単にできます。

class User < ApplicationRecord
  validates :terms_of_service, acceptance: { accept: 'yes' }
  validates :eula, acceptance: { accept: ['TRUE', 'accepted'] }
end

validates_associatedの使い方

alidates_associatedバリデーションは、関連するモデルを検証するバリデーションです。

モデルAとモデルBが関連している場合、モデルAの保存時に自動的にモデルBのバリデーションが実行されます。

例えば、投稿を行うアプリケーションでは、投稿に紐づくコメントがあります。
投稿を保存する際に、その投稿に紐づくコメントのバリデーションも同時に行いたいときvalidates_associatedバリデーションを使用できます。

具体的には、モデルで以下のように定義します。

class Post < ApplicationRecord
  has_many :comments
  validates_associated :comments
end

これにより、投稿を保存する際に自動的にコメントのバリデーションを実行させることができます。

validates_withの使い方

validates_withメソッドは、ActiveModelのバリデーション機能を使って、独自のバリデーションを定義するときに使用します。
これにより、任意のカスタムバリデータを作成し、そのバリデータをモデルに適用することができます。

以下は、validates_withを使用して独自のカスタムバリデーションを作成する手順です。

まず、バリデーションを実行するためのカスタムバリデータクラスを作成する必要があります。 このクラスは、ActiveModel::Validatorを継承する必要があります。

class MyValidator < ActiveModel::Validator
  def validate(record)
    # validation logic here
  end
end

次に、validates_withメソッドを使用して、先程作成したバリデータクラスをモデルに適用します。

class MyModel < ActiveRecord::Base
  validates_with MyValidator
end

最後に、カスタムバリデーションクラスでvalidateメソッドを実装して、バリデーションロジックを定義します。validateメソッドは、引数としてモデルのインスタンスを受け取ります。

class MyValidator < ActiveModel::Validator
  def validate(record)
    if record.some_attribute == "invalid"
      record.errors.add :some_attribute, "is invalid"
    end
  end
end

上記の例では、モデルのsome_attributeが「invalid」である場合にエラーを追加しています。

record.errorsオブジェクトは、ActiveModel::Errorsオブジェクトで、モデルのエラーメッセージを格納するために使用されます。

validates_eachの使い方

validates_eachメソッドは、ActiveModelのバリデーション機能を使って、1つのブロックに対して独自のバリデーションを定義することができます。

定義済みのバリデーション関数はないため、ブロックを使うバリデーションを自分で作成します。

以下は、validates_eachを使用して独自のカスタムバリデーションを作成する例です。

class MyModel < ActiveRecord::Base
  validates_each :attribute_name do |record, attr, value|
    unless value.is_valid?
      record.errors.add(attr, "is not valid")
    end
  end
end

このブロックは、レコード(record)と属性の名前(attr)、そして属性の値(value)を受け取ります。

ブロック内で、属性の値をチェックし、エラーがある場合はエラーメッセージを追加します。

上記の例では、属性attribute_nameの値がis_valid?でない場合、エラーメッセージが追加されます。record.errorsオブジェクトは、ActiveModel::Errorsオブジェクトで、モデルのエラーメッセージを格納するために使用されます。

最後に、モデルをバリデーションする方法です。
通常のバリデーションのように、valid?メソッドを呼び出します。

model = MyModel.new(attribute_name: 'invalid value')
model.valid? # => false
model.errors[:attribute_name] # => ['is not valid']

上記の例では、attribute_nameの値が”invalid value”であるため、valid?メソッドはfalseを返し、エラーメッセージがmodel.errorsオブジェクトに追加されます。

共通のバリデーションオプション

allow_nilの使い方

allow_nilオプションは、バリデーションを行う際に、対象となる属性の値がnilであってもバリデーションを通過することを許可するためのオプションです。

allow_nilを使用すると、presenceバリデーションなど、属性が空であることを検証するバリデーションでnilの値が許容されるように変更できます。

例えば、以下のようなコードを書くことができます。

class User < ApplicationRecord
  validates :name, presence: true, allow_nil: true
end

このコードでは、Userモデルのname属性に対して、presenceバリデーションを適用し、allow_nilオプションを追加しています。
そのため、このバリデーションではnameカラムの値がnilである場合はバリデーションを通過します。

allow_nilオプションは、バリデーションが必要ない場合に便利です。
例えば、オプションの属性が設定されていない場合にはバリデーションを実行せず、属性が設定されている場合には属性が適切な値であるかどうかを検証するというような使い方ができます。

allow_blankの使い方

allow_blankオプションは、バリデーションを行う際に、対象となる属性の値がnilや空白文字列("")など空の状態のとき(値がblank?に該当するとき)にバリデーションを通過することを許可するためのオプションです。

allow_blankを使用すると、presenceバリデーションなど属性が空であることを検証するバリデーションで空白文字列が許容されるように変更できます。

例えば、以下のようなコードを書くことができます。

class User < ApplicationRecord
  validates :name, presence: true, allow_blank: true
end

このコードでは、Userモデルのname属性に対して、presenceバリデーションを適用し、allow_blankオプションを追加しています。
そのため、nameカラムの値が空白文字列である場合もバリデーションを通過します。

messageの使い方

messageオプションは、バリデーションが失敗した場合に表示するエラーメッセージを指定するためのオプションです。

例えば、以下のようなバリデーションコードがあるとします。

class User < ApplicationRecord
  validates :name, presence: true
end

この場合、name属性が空である場合にバリデーションが失敗し、「Name can’t be blank」というエラーメッセージが自動的に生成されます。

こちらのデフォルトのエラーメッセージの内容を変更したいときはmessageオプションを使用することで、独自のエラーメッセージを指定できます。

例えば、以下のように書くことができます。

class User < ApplicationRecord
  validates :name, presence: { message: "Please enter your name." }
end

上記のコードにすることで、nameカラムが空でバリデーションが失敗した場合に、「Please enter your name.」という独自のエラーメッセージが表示されます。

messageオプションは、バリデーションが失敗した場合にユーザーに対して適切な情報を提供するための重要な役割をします。

複数のバリデーションを適用する場合には、各バリデーションごとに異なるエラーメッセージを指定することができるため、エラーの原因が明確になります。

onの使い方

onオプションは、どのタイミングでバリデーションを実行するかを指定するためのオプションです。

デフォルトでは、Railsはオブジェクトが保存される前にすべてのバリデーションを実行します。
しかし、onオプションを使用すると、特定のタイミングでのみバリデーションを実行することができます。

onオプションで指定できる値は以下の通りです。

メソッド説明
create新規作成時のみバリデーションを実行する
update更新時のみバリデーションを実行する
save保存時にバリデーションを実行する
validationバリデーション時に常に実行する(デフォルト)

例えば、以下のようなコードを書くことができます。

class User < ApplicationRecord
  validates :email, presence: true, on: :create
end

このコードでは、email属性に対してpresenceバリデーションを適用しています。
また、on: :createオプションを指定することで、新規作成時のみバリデーションを実行するように設定しています。
これにより、既存のレコードを更新する場合にはemail属性が空であっても保存ができるようになります。

onオプションを使用することで、必要なタイミングでバリデーションを実行することができ、より柔軟なバリデーションの設定が可能になります。

条件付きバリデーション

条件付きバリデーションとは、ある特定の条件を満たしたときに実行したいバリデーションのことです。
標準のバリデーションだけでは対応できない場合に使用されます。
例えば、あるカラムが特定の値を持っているときに、そのカラムに対するバリデーションを実行する、といった使い方ができます。

条件付きバリデーションを実装する方法は複数ありますが、一般的には、ifunlessオプションを使用する方法が使われます。

これらのオプションを使用することで、特定の条件を指定し、その条件が満たされた場合にバリデーションを実行するように設定することができます。

以下は、ifオプションを使用した例です。

class User < ApplicationRecord
  validates :email, presence: true, if: :email_required?

  def email_required?
    true
  end
end

上記の例では、emailカラムに対して、presenceバリデーションが設定されていますが、ifオプションでemail_required?メソッドを指定しています。

このメソッドがtrueを返す場合には、presenceバリデーションが実行されます。

class User < ApplicationRecord
  with_options if: :is_admin? do |admin|
    admin.validates :email, presence: true
    admin.validates :password, presence: true
  end

  def is_admin?
    true
  end
end

上記の例では、is_admin?メソッドがtrueを返す場合には、emailカラムとpasswordカラムに対してpresenceバリデーションが実行されます。

以上のように、ifunlessオプションを使用することで、条件付きバリデーションを簡単に実装することができます

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次