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.