Ruby on Rails ActiveRecord Validations Custom validations


Example

You can add your own validations adding new classes inheriting from ActiveModel::Validator or from ActiveModel::EachValidator. Both methods are similar but they work in a slightly different ways:

ActiveModel::Validator and validates_with

Implement the validate method which takes a record as an argument and performs the validation on it. Then use validates_with with the class on the model.

# app/validators/starts_with_a_validator.rb
class StartsWithAValidator < ActiveModel::Validator
  def validate(record)
    unless record.name.starts_with? 'A'
      record.errors[:name] << 'Need a name starting with A please!'
    end
  end
end
 
class Person < ApplicationRecord
  validates_with StartsWithAValidator
end

ActiveModel::EachValidator and validate

If you prefer to use your new validator using the common validate method on a single param, create a class inheriting from ActiveModel::EachValidator and implement the validate_each method which takes three arguments: record, attribute, and value:

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
      record.errors[attribute] << (options[:message] || 'is not an email')
    end
  end
end
 
class Person < ApplicationRecord
  validates :email, presence: true, email: true
end

More information on the Rails guides.