ruby-on-railsvalidationactivemodel

Mix create and update validations in single custom validator using ActiveModel::Validator


I found two alternatives to make use of the ActiveModel::Validator helper, but I am failing to find an easier or clean(er) approach than either checking for the presence of record.id or creating multiple custom validators.

I have a User class as follows:

class User < ApplicationRecord
  include ActiveModel::Validations

  validates_with UserValidator

  ...
end

and a custom validator

class UserValidator < ActiveModel::Validator
  def validate(record)
    # validate some stuff
  end
end

The logic inside the validate method is executed no matter the action from the controller. So on create or on update (or save).

My goal is to split the logic and I have found multiple approaches that work but I don't really like either of them.

Approach 1: Check if a record.id exists

class UserValidator < ActiveModel::Validator
  def validate(record)
    if record.id.nil?
      # `on: :create` validations
    else
      # `on: :update` validations
    end
  end
end

Approach 2: Create multiple validator classes

class User < ApplicationRecord
  include ActiveModel::Validations

  validates_with UserCreateValidator, on: :create
  validates_with UserUpdateValidator, on: :update

  ...
end

Preferably I would only have a single class UserValidator and within that custom validator check for some attribute or pass an option that would allow me to distinguish between create or update. Is that somehow achievable?


Solution

  • class UserValidator < ActiveModel::Validator
      def validate(record)
        if record.new_record?
          # `on: :create` validations
        else
          # `on: :update` validations
        end
      end
    end
    

    See ActiveRecord::Persistence.