Paul
Paul

Reputation: 26660

Rails conditional validation of Zip Code for many countries

I need a model-level validation for Zip codes in USA and Canada. This code makes me feel bad:

zip_regex_usa = %r{\d{5}(-\d{4})?}
zip_regex_canada = %r{[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d}

validates :shipping_zip, :presence => true, :format => { :with => zip_regex_usa }, :if => :shipping_to_usa?
validates :shipping_zip, :presence => true, :format => { :with => zip_regex_canada }, :if => :shipping_to_canada?
validates :billing_zip, :presence => true, :format => { :with => zip_regex_usa }, :if => :billing_to_usa?
validates :billing_zip, :presence => true, :format => { :with => zip_regex_canada }, :if => :billing_to_canada?

def shipping_to_usa?
  shipping_country == 'US'
end

def billing_to_usa?
  billing_country == 'US'
end

def shipping_to_canada?
  shipping_country == 'CA'
end

def billing_to_canada?
  billing_country == 'CA'
end

How to make this code more elegant, writing a single validation line for each field?

Upvotes: 1

Views: 5916

Answers (2)

dgilperez
dgilperez

Reputation: 10796

I pulled some bits together into this gem: validates_zipcode.

It currently supports 259 countries zipcode formats and plays nice with Rails 3 & 4.

You can use it like this:

class Address < ActiveRecord::Base
  validates_zipcode :zipcode
  validates :zipcode, zipcode: true
  validates :zipcode, zipcode: { country_code: :ru }
  validates :zipcode, zipcode: { country_code_attribute: :my_zipcode }
end

Upvotes: 0

Said Kaldybaev
Said Kaldybaev

Reputation: 9962

You can use gem validates_as_postal_code

It allows you to check zip codes like this:

class Person < ActiveRecord::Base
   validates_as_postal_code :postal_code, :country => "CA", :allow_blank => true
end

and there're more options

EDIT: There's also one nice gem: going_postal check it out!

Upvotes: 1

Related Questions