Here's a handy trick for making custom validations easily reusable.
This is an extract from a customer model with three different street addresses, in which we validate all three of the zip codes. (In this code, the GeoState.valid_zip_code? method answers if something that looks like a zip code is an actual zip code - not all five digit combinations are in use as zip codes, and we want to make sure we've got a live one.)
def validate_home_zip_code
validate_zip_code(:home_zip_code)
end
def validate_mailing_zip_code
validate_zip_code(:mailing_zip_code)
end
def validate_previous_zip_code
validate_zip_code(:previous_zip_code)
end
def validate_zip_code(field)
errors.add(field, :inclusion) if errors.on(field).nil? && !GeoState.valid_zip_code?(send(field))
end
validates_presence_of :home_zip_code
validates_format_of :home_zip_code, :with => /^\d{5}(-\d{4})?$/, :allow_blank => true
validate :validate_home_zip_code
validates_presence_of :mailing_zip_code
validates_format_of :mailing_zip_code, :with => /^\d{5}(-\d{4})?$/, :allow_blank => true
validate :validate_mailing_zip_code
validates_presence_of :previous_zip_code
validates_format_of :previous_zip_code, :with => /^\d{5}(-\d{4})?$/, :allow_blank => true
validate :validate_previous_zip_code
That looks very wet to me. (WET == "Write Every Time") But it's not too hard to dry this up using just a tiny bit of knowledge of how ActiveRecord validations work.
