Railsで特定のコントローラーからバリデーションを制御する

フリーランスでシステムエンジニアしております。

Active Record バリデーションについての備忘録です。

  • 特定の条件下で使いたい
  • saveしている箇所から使用するバリデーションを制御したい

if等を使用した条件付きバリデーション

:ifや:unlessでシンボルを使う

バリデーションの実行直前に呼び出されるメソッド名を、:if:unlessオプションにシンボルで指定することもできます。 これは最もよく使われるオプションです。

class Order < ApplicationRecord
  validates :card_number, presence: true, if: :paid_with_card?

  def paid_with_card?
    payment_type == "card"
  end
end

条件付きバリデーションをグループ化する

1つの条件を複数のバリデーションで共用できると便利なことがあります。これはwith_optionsで簡単に実現できます。

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

with_optionsブロックの内側にあるすべてのバリデーションにif: :is_admin?という条件が渡されます。

onを使用した条件分岐

:onオプションは、バリデーション実行のタイミングを指定します。

create, update

on: :createを指定すればレコード新規作成時にのみバリデーションが行われ、on: :updateを指定すればレコードの更新時にのみバリデーションが行われます。

class Person < ApplicationRecord
  # 値が重複していてもemailを更新できる
  validates :email, uniqueness: true, on: :create

  # 新規レコード作成時に、数字でない年齢表現を使える
  validates :age, numericality: true, on: :update

  # デフォルト (作成時と更新時の両方でバリデーションを行なう)
  validates :name, presence: true
end

カスタムコンテキスト

on:にはカスタムコンテキストも定義できます。カスタムコンテキストは、valid?invalid?saveにコンテキスト名を渡して明示的にトリガーする必要があります。

class Person < ApplicationRecord
  with_options on: :account_setup do
    validates :email, uniqueness: true
    validates :age, numericality: true
  end
end

valid? は以下のようにします。(モデルを保存せずにバリデーションを2つとも実行します)

person.valid?(:account_setup)

save は以下のように指定します。(保存の前にaccount_setupコンテキストでpersonを検証します)

person.save(context: :account_setup)

update はcontextオプションは使えない

update で同じことをやりたい場合は、attributesにセットしてからsaveメソッドを使えばできます。

person.update(update_params)

上記を以下のようにします。

person.attributes = update_params
person.save(context: :account_setup)

RSpec

be_valid 使うときはコンテキスト名を渡します

expect(person).to be_valid :account_setup

エラーメッセージの確認は、始めにvalid? します。

person.valid?(:account_setup)
expect(person.errors[:email]).to be_present

まとめ

  • :ifオプションは「特定の条件を満たす場合にのみバリデーションを実行したい場合」に使います。主にモデルの状態から判定します。
  • カスタムコンテキスト(:on) は便利な機能です。これを使うと使用している箇所から制御できますね。👍

参考サイト

Active Record バリデーション

3.4 :on

5 条件付きバリデーション

Railsガイド

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA