-
-
Save dgilperez/6232901 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/user.rb | |
class User < ActiveRecord::Base | |
validates :zipcode, presence: true, zipcode: true | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/validators/zipcode_validator.rb | |
# Usage: | |
# | |
# class User << AR | |
# validates :postalcode, zipcode: true | |
# | |
# # Required country_alpha2 attribute | |
# def country_alpha2 | |
# country.alpha2 | |
# end | |
# end | |
# | |
class ZipcodeValidator < ActiveModel::EachValidator | |
# using country alpha2 code as key | |
ZIPCODES_REGEX = { | |
ES: /\A\d{5}\z/, | |
AR: /\A([A-HJ-TP-Z]{1}\d{4}[A-Z]{3}|[a-z]{1}\d{4}[a-hj-tp-z]{3})\z/, | |
NZ: /\A\d{4}\z/, | |
AU: /\A\d{4}\z/, | |
US: /\A\d{5}(-\d{4})?\z/, | |
CA: /\A[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTWVXYZ]\d[ABCEGHJKLMNPRSTWVXYZ]\d\z/ | |
} | |
def validate_each(record, attribute, value) | |
alpha2 = record.country_alpha2.try(:to_sym) | |
unless alpha2 && ZIPCODES_REGEX[alpha2].match(value) | |
record.errors.add(attribute, "#{value} is not a valid zipcode") | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# spec/lib/validators/zipcode_validator_spec.rb | |
require 'spec_helper' | |
describe ZipcodeValidator, '#validate_each' do | |
context "Spain" do | |
it 'does not add errors with a valid zipcode' do | |
record = build_record('93108', "ES") | |
zipcode_should_be_valid(record) | |
end | |
it 'adds errors with an invalid Zipcode' do | |
['1234', '12345-12345', 'D0D0D0', 'invalid_zip'].each do |zipcode| | |
record = build_record(zipcode, 'ES') | |
zipcode_should_be_invalid(record, zipcode) | |
end | |
end | |
end | |
context "USA" do | |
it 'does not add errors with a valid zipcode' do | |
record = build_record('93108', "US") | |
zipcode_should_be_valid(record) | |
['12345', '12345-1234'].each do |zipcode| | |
record = build_record(zipcode, 'US') | |
zipcode_should_be_valid(record) | |
end | |
end | |
it 'adds errors with an invalid Zipcode' do | |
['1234', '12345-12345', 'D0D0D0', 'invalid_zip'].each do |zipcode| | |
record = build_record(zipcode, 'US') | |
zipcode_should_be_invalid(record, zipcode) | |
end | |
end | |
end | |
context "Argentina" do | |
it 'does not add errors with a valid zipcode' do | |
record = build_record('C1424CHN', "AR") | |
zipcode_should_be_valid(record) | |
end | |
it 'adds errors with an invalid Zipcode' do | |
['1234', '12345', 'D0D0D0', 'invalid_zip'].each do |zipcode| | |
record = build_record(zipcode, 'AR') | |
zipcode_should_be_invalid(record, zipcode) | |
end | |
end | |
end | |
context "Australia and New Zeland" do | |
it 'does not add errors with a valid zipcode' do | |
["AU", "NZ"].each do |code| | |
record = build_record('9310', code) | |
zipcode_should_be_valid(record) | |
end | |
end | |
it 'adds errors with an invalid Zipcode' do | |
["AU", "NZ"].each do |code| | |
['C1424CHN', '12345', 'invalid_zip'].each do |zipcode| | |
record = build_record(zipcode, code) | |
zipcode_should_be_invalid(record, zipcode) | |
end | |
end | |
end | |
end | |
context "Canada" do | |
it 'does not add errors with a valid zipcode' do | |
record = build_record('A1J2Z9', 'CA') | |
zipcode_should_be_valid(record) | |
end | |
it 'adds errors with an invalid Zipcode' do | |
['C1424CHN', '12345', 'D0D0D0', 'invalid_zip'].each do |zipcode| | |
record = build_record(zipcode, 'CA') | |
zipcode_should_be_invalid(record, zipcode) | |
end | |
end | |
end | |
def zipcode_should_be_valid(record) | |
ZipcodeValidator.new(attributes: :zipcode).validate(record) | |
record.errors.should be_empty | |
end | |
def zipcode_should_be_invalid(record, zipcode = "invalid_zip") | |
ZipcodeValidator.new(attributes: :zipcode).validate(record) | |
record.errors.full_messages.should eq [ | |
"Zipcode #{zipcode} is not a valid zipcode" | |
] | |
end | |
def build_record(zipcode, country_alpha2) | |
test_class.new.tap do |object| | |
object.country_alpha2 = country_alpha2 | |
object.zipcode = zipcode | |
end | |
end | |
def test_class | |
Class.new do | |
include ActiveModel::Validations | |
attr_accessor :zipcode, :country_alpha2 | |
def self.name | |
'TestClass' | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment