Conditional validation on model dependent on value of model attribute
I'm struggling with validating a postal_code and using a different regex depending on what the country_code attribute is. I tried the following, but it does not work:
class Venue < ActiveRecord::Base
...
attr_accessible :postal_code
attr_accessible :country_code
...
validates_presence_of :country_code
validates_length_of :country_code, :maximum => 2, :allow_nil => true
validates_inclusion_of :country_code, :in => %w( US CA AU GB )
validates_presence_of :postal_code
validates_length_of :postal_code, :maximum => 10, :allow_nil => true
validates_format_of :postal_code, :with => %r{^\d{4}$},
:message => "should be in the format 1111",
:allow_nil => true,
:if => :country_code == 'AU'
validates_format_of :postal_code, :with => %r{^\d{5}([\-]\d{4})?$},
:message => "should be in the format 11111 or 11111-1111",
:allow_nil => true,
:if => :country_code == 'US'
validates_format_of :postal_code, :with =&g开发者_运维百科t;%r{^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$},
:message => "should be in the format A1A 1A1 (try making letters capitalized)",
:allow_nil => true,
:if => :country_code == 'CA'
# ridculously long (but thorough) regex courtesy of Wikipedia (http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom)
validates_format_of :postal_code, :with => %r{^(GIR 0AA)|(((A[BL]|B[ABDHLNRSTX]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|((E|N|NW|SE|SW|W)1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|(SW|W)([2-9]|[1-9][0-9])|EC[1-9][0-9]) [0-9][ABD-HJLNP-UW-Z]{2})$},
:message => "invalid postal code (try making letters capitalized)",
:allow_nil => true,
:if => :country_code == 'GB'
Am I totally off the reservation on this, or is it just the format of the :if
options that are hosed up?
For reference, the :if =>
parameter accepts a method rather than a condition, you can for example do
validate_presence_of :foo, :if => :country_is_gb?
def country_is_gb?
country_code == 'GB'
end
But as mentioned, lengthy or complex validations are best done in a seperate custom validator.
Take a look at this screencast http://asciicasts.com/episodes/211-validations-in-rails-3 I think its just about time to write a custom validator function for your postal code.
精彩评论