Search code examples
ruby-on-railsvalidationcustom-validators

Refactoring custom validation for multiple fields in model


I have a model with a custom validation function which verifies that the date is not in the past. Currently, the validation is hard-coded to check a single field, selected_date, in the model. How do I go about refactoring the validation so that I can either pass a parameter to the custom validation so I can test 2 fields?

class Appointment < ActiveRecord::Base
  attr_accessible :selected_date, :alternate_date

  validates_presence_of :selected_date
  validate :validate_date

  def validate_date
    if selected_date < Date.today
      errors.add(:selected_date, 'Date has passed')
    end
  end
end

Solution

  • create file lib/future_validator.rb:

    class FutureValidator < ActiveModel::EachValidator
    
      def validate_each(object, attribute, value)
        if value < Date.today
          object.errors[attribute] << "has passed"
        end
      end
    
    end
    

    In your models:

    validates :selected_date, presence: true, future: true
    validates :other_date, presence: true, future: true
    

    See this RailsCast: Validations in Rails 3

    NOTE: Make sure lib files are auto loaded in config/application.rb and restart the server after adding that file.