Change priority of Custom validations in rails model

479 views Asked by At

I have implemented validations in a dependent manner, like if start_date format is invalid so i don't want to run other validation on start_date.

 validates_format_of :available_start_date, :with =>  /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}((((\-|\+){1}\d{2}:\d{2}){1})|(z{1}|Z{1}))$/, :message => "must be in the following format: 2011-08-25T00:00:00-04:00"

This checks for a specific format and then i have custom validation methods called from which should run later.

def validate
  super
  check_offer_dates
end

I have used self.errors["start_date"] to check if the error object contains errors, it should skip the other validations on same parameter if it's not empty.

But the problem is def validate is called first and then the validates_format_of. How can i change this so that the flow can be achieved.

1

There are 1 answers

0
johnd On

I just ran into a similar problem; this is how I fixed it using a before_save callout:

Not working (validates in wrong order - I want custom validation last):

class Entry < ActiveRecord::Base
   validates_uniqueness_of :event_id, :within => :student_id
   validate :validate_max_entries_for_discipline

   def validate_max_entries_for_discipline
      # set validation_failed based on my criteria - you'd have your regex test here
      if validation_failed
         errors.add(:maximum_entries, "Too many entries here")
      end
   end
end

Working (using before_save callout):

class Entry < ActiveRecord::Base
   before_save :validate_max_entries_for_discipline!
   validates_uniqueness_of :event_id, :within => :student_id

   def validate_max_entries_for_discipline!
      # set validation_failed based on my criteria - you'd have your regex test here
      if validation_failed
         errors.add(:maximum_entries, "Too many entries here")
         return false
      end
   end
end

Note the changes:

  1. validate_max_entries_for_discipline becomes validate_max_entries_for_discipline!
  2. validation method now returns false on failure
  3. validate validate_max_entries_for_discipline becomes before_save validate_max_entries_for_discipline!