Class: ActiveModel::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/active_model/validator.rb

Overview

Active Model Validator

A simple base class that can be used along with ActiveModel::Validations::ClassMethods.validates_with

class Person
  include ActiveModel::Validations
  validates_with MyValidator
end

class MyValidator < ActiveModel::Validator
  def validate(record)
    if some_complex_logic
      record.errors[:base] = "This record is invalid"
    end
  end

  private
    def some_complex_logic
      # ...
    end
end

Any class that inherits from ActiveModel::Validator must implement a method called validate which accepts a record.

class Person
  include ActiveModel::Validations
  validates_with MyValidator
end

class MyValidator < ActiveModel::Validator
  def validate(record)
    record # => The person instance being validated
    options # => Any non-standard options passed to validates_with
  end
end

To cause a validation error, you must add to the record‘s errors directly from within the validators message.

class MyValidator < ActiveModel::Validator
  def validate(record)
    record.errors.add :base, "This is some custom error message"
    record.errors.add :first_name, "This is some complex validation"
    # etc...
  end
end

To add behavior to the initialize method, use the following signature:

class MyValidator < ActiveModel::Validator
  def initialize(options)
    super
    @my_custom_field = options[:field_name] || :first_name
  end
end

Note that the validator is initialized only once for the whole application life cycle, and not on each validation run.

The easiest way to add custom validators for validating individual attributes is with the convenient ActiveModel::EachValidator.

class TitleValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors.add attribute, 'must be Mr., Mrs., or Dr.' unless %w(Mr. Mrs. Dr.).include?(value)
  end
end

This can now be used in combination with the validates method (see ActiveModel::Validations::ClassMethods.validates for more on this).

class Person
  include ActiveModel::Validations
  attr_accessor :title

  validates :title, presence: true, title: true
end

Validator may also define a setup instance method which will get called with the class that using that validator as its argument. This can be useful when there are prerequisites such as an attr_accessor being present.

class MyValidator < ActiveModel::Validator
  def setup(klass)
    klass.send :attr_accessor, :custom_attribute
  end
end

This setup method is only called when used with validation macros or the class level validates_with method.

Direct Known Subclasses

EachValidator

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Validator

Accepts options that will be made available through the options reader.



109
110
111
# File 'lib/active_model/validator.rb', line 109

def initialize(options = {})
  @options = options.freeze
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



98
99
100
# File 'lib/active_model/validator.rb', line 98

def options
  @options
end

Class Method Details

.kindObject

Returns the kind of the validator.

PresenceValidator.kind   # => :presence
UniquenessValidator.kind # => :uniqueness


104
105
106
# File 'lib/active_model/validator.rb', line 104

def self.kind
  @kind ||= name.split('::').last.underscore.sub(/_validator$/, '').to_sym unless anonymous?
end

Instance Method Details

#kindObject

Return the kind for this validator.

PresenceValidator.new.kind   # => :presence
UniquenessValidator.new.kind # => :uniqueness


117
118
119
# File 'lib/active_model/validator.rb', line 117

def kind
  self.class.kind
end

#validate(record) ⇒ Object

Override this method in subclasses with validation logic, adding errors to the records errors array where necessary.

Raises:

  • (NotImplementedError)


123
124
125
# File 'lib/active_model/validator.rb', line 123

def validate(record)
  raise NotImplementedError, "Subclasses must implement a validate(record) method."
end