概要

Railsアプリを作っていると、特定の属性が変更された場合にだけバリデーションを実行したいことがあります。そんな時に使えるのが、ActiveModel::Dirtyモジュールです。このモジュールには、属性の変更をキャッチする便利なメソッドがいくつか含まれています。

属性変更時のみバリデーションを実行する方法

基本の例

まず、特定の属性が変更されたときだけバリデーションを実行する条件をモデルに追加します。例えば、name属性が変更されたときだけバリデーションを実行する場合はこんな感じです。

class User < ApplicationRecord
  validate :name_changed_validation, if: :name_changed?

  private

  def name_changed_validation
    if name.blank?
      errors.add(:name, "can't be blank")
    end
  end
end

この例では、name属性が変更されたときに、nameが空でないかどうかをチェックしています。name_changed?メソッドは、name属性が変更されたかどうかを確認します。

ほかのメソッドを使った例

特定の属性が変更されたかをチェックするには、will_save_change_to_attribute?メソッドも使えます。例えば、email属性のフォーマットを確認したい場合はこんな感じです。

class User < ApplicationRecord
  validate :email_format, if: -> { will_save_change_to_attribute?(:email) }

  private

  def email_format
    unless email =~ /\A[^@\s]+@[^@\s]+\z/
      errors.add(:email, "is not a valid email")
    end
  end
end

この例では、email属性が変更されたときにだけ、emailのフォーマットをチェックしています。

まとめ

ActiveModel::Dirtyモジュールを使えば、特定の属性が変更されたときだけバリデーションを実行することができます。これで、効率的かつ必要な場合にだけバリデーションをかけることができますね。モデルの特定の属性に変更があった場合にだけバリデーションを実行することで、より柔軟なバリデーションを実現しましょう。