0
0

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】カスタムバリデータ

Posted at

はじめに

カスタムバリデータを実装する機会があったので、学習内容をまとめます。

カスタムバリデータ

メリット

  • 組み込みのバリデータだけでは足りない場合に独自のバリデータを追加できる
  • 特定のモデルから分離して定義し、複数のモデルで共通利用できる=繰り返しの記述を防ぐことができる

組み込みバリデータ

バリデータ バリデーション内容
absence 存在してはならないこと
acceptance フォームが送信されたときにユーザーインターフェイス上のチェックボックスがオンになっているか
confirmation 2つのテキストフィールドの入力内容が完全に一致するか
comparison 比較可能な2つの値を比較
format withオプションで与えられた正規表現と属性の値がマッチするか
inclusion 値がセット内に存在すること
exclusion 値がセット内に存在しないこと
length 属性の値の長さを検証
numericality 属性に数値のみが使われていること
presence 指定された属性が空(empty)でないこと
uniqueness オブジェクトが保存される直前に、属性の値が一意(unique)であり重複していないこと
validates_associated 常に有効でなければならない関連付けがモデルにある場合、オブジェクトを保存しようとするたびに、関連付けられているオブジェクトごとにvalid?を呼び出す
validates_each 属性をブロックでバリデーションする。バリデーション関数を独自に作成する必要がある
validates_with バリデーション専用の別クラスにレコードを渡す。バリデーション専用の別クラスは独自に作成する必要がある

定義方法(ActiveModel::Validator)

  • app/models配下に直接ファイルを作成するか、validatorディレクトリを作成してそこにまとめてファイルを配置する

  • validate メソッドを定義する

  • 引数にrecord (バリデーション対象のオブジェクト)を一つ取る

class HogeValidator < ActiveModel::Validator
  def validate(record) # レコードを一つ引数に取る
    unless record.name.start_with? "X"  # record に対するバリデーションルール
      record.errors.add :name, "名前はXで始まる必要があります"
    end
  end
end
  • validates_with メソッドで呼び出す
class Hoge < ApplicationRecord
  validates_with HogeValidator
end

定義方法(ActiveModel::EachValidator)

  • validate_each メソッドをていg
  • recordattributevalue の三つの引数を取る
    • record : バリデーション対象のオブジェクト
    • attribute : バリデーション対象の属性名
    • value : バリデーション対象の属性値
class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless URI::MailTo::EMAIL_REGEXP.match?(value) # valueに対するバリデーションルール
      record.errors.add attribute, (options[:message] || "はメールアドレスではありません")
    end
  end
end
  • 標準のバリデーションと組み合わせて呼び出す
    • カスタムバリデータのクラス名を XXXValidator とすると、xxx: true と指定する(例:EmailValidatorをカスタムバリデータのクラス名とした場合、email: true と指定する)
class Person < ApplicationRecord
  validates :email, email: true
end

その他のカスタム

カスタムメソッド

  • 定義方法
    • validate :カスタムメソッド名 の形でシンボルで渡す
    • 複数のシンボルを渡せる
    • バリデーションは登録されたとおりの順序で実行される
class Invoice < ApplicationRecord
  validate :expiration_date_cannot_be_in_the_past,
    :discount_cannot_be_greater_than_total_value

  def expiration_date_cannot_be_in_the_past
    if expiration_date.present? && expiration_date < Date.today
      errors.add(:expiration_date, "過去の日付は使えません")
    end
  end

  def discount_cannot_be_greater_than_total_value
    if discount > total_value
      errors.add(:discount, "合計額を上回ることはできません")
    end
  end
end

  • :on オプションを使えば、カスタムバリデーションが実行されるタイミングを変更できる
  • 使えるのは on: :create on: :update
class Invoice < ApplicationRecord
  validate :active_customer, on: :create

おわりに

validatesとvalidateの使い分けがややこしいです。カスタムバリデータを定義する時はvalidate、呼び出す時はvalidatesです。ただし、カスタムメソッドはvalidateで登録します。

参考

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?