3

I'm trying to move my validations to a module. I want to extend an existing object an aribtrary set of validators, but I'm struggling to figure out how to get them to execute. Any ideas?

Active Record Object

class Test < ActiveRecord::Base
  has_many :resources
end

Validator

module TestValidator
  extend ActiveSupport::Concern

  included do
    validates_associated :resources
  end
end

Console

t = Test.new
t.extend TestValidator
t.valid?
# true ... should be false
Allyl Isocyanate
  • 13,306
  • 17
  • 79
  • 130

1 Answers1

5

I hope this can help

6.1 Custom Validators Custom validators are classes that extend ActiveModel::Validator. These classes must implement a validate method which takes a record as an argument and performs the validation on it. The custom validator is called using the validates_with method.

class MyValidator < ActiveModel::Validator
  def validate(record)
    unless record.name.starts_with? 'X'
      record.errors[:name] << 'Need a name starting with X please!'
    end
  end
end



class Person
  include ActiveModel::Validations
  validates_with MyValidator
end

The easiest way to add custom validators for validating individual attributes is with the convenient ActiveModel::EachValidator. In this case, the custom validator class must implement a validate_each method which takes three arguments: record, attribute and value which correspond to the instance, the attribute to be validated and the value of the attribute in the passed instance.

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 < ActiveRecord::Base
  validates :email, :presence => true, :email => true
end

As shown in the example, you can also combine standard validations with your own custom validators.

https://guides.rubyonrails.org/active_record_validations.html#custom-validators

Amree
  • 2,890
  • 3
  • 30
  • 51
Ben Zhang
  • 1,281
  • 11
  • 14
  • 1
    Hey Ben, thanks for your post. This is definitely the sane/right way to do validations. I was trying to get a module/mixin approach going however, the reason being I was trying to use validations in a DCI sense, that there was a "TestValidator" role. But after thinking about it more, I think the standard approach you pointed out above works better, because in some sense validations are data. – Allyl Isocyanate Jan 27 '12 at 14:53