validates_uniqueness_of works by checking if a record with the same value of a given field exists within a given scope. :scope allows you to define the scope of uniqueness; for example, if I was creating blog software and only wanted one post title for one blog, I could say validates_uniqueness_of :title, :scope => :blog_id - no frame, I would only allow each title to be used once per the whole system. :scope will not allow you to perform complex validation like what you want.
What you probably need to do is create your own validation function to verify the uniqueness of the field in question for a given time interval (the code is included in the model):
validate :field_must_be_unique_within_six_months def field_must_be_unique_within_six_months return if field.blank? num_duplicates = self.class.count(:conditions => ["field = ? AND created_at < ?", self.field, 6.months.ago]) if num_duplicates > 0 errors.add(:field, :taken) end end
The field_must_be_unique_within_six_months method will work similarly to validates_uniqueness_of , because it will add an error message if there is already an entry with the same field specified, but with the added condition that it also checks the date. validate :field_must_be_unique_within_six_months will add the method to the validation process when the record is saved.
To check multiple fields at the same time without violating DRY, you can use validates_each to do something like the following:
validates_each :field1, :field2 do |record, attr, value| if record.class.exists?(["#{attr.to_s} = ? AND created_at < ?", value, 6.months.ago]) errors.add(attr, :taken) end end
In the record block above, the record checked, attr is the attribute (therefore field1 , field2 , etc.), and value is the value of this attribute.