Skip to content

Instantly share code, notes, and snippets.

@mmrwoods
Last active January 1, 2016 05:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmrwoods/8099688 to your computer and use it in GitHub Desktop.
Save mmrwoods/8099688 to your computer and use it in GitHub Desktop.
Postal code validation example
class Address < ActiveRecord::Base
attr_accessible :line_1, :line_2, :line_3, :town, :region, :postcode
validates :line_1, :postcode, :presence => true
validates :postcode, :postcode => true, :allow_blank => true
after_validation do
self.postcode = PostalCode.new(self.postcode).to_formatted_s
end
end
# make ffaker return a valid uk postcode
# this is not pretty, I have no shame
Faker::AddressUK.module_eval do
def postcode_with_validation
begin
postcode = Faker::AddressUK.postcode_without_validation
end until PostalCode.new(postcode, "GB").valid?
return postcode
end
alias_method_chain :postcode, :validation
end
require'going_postal'
class PostalCode
def initialize(postcode, country_code=nil)
@postcode = postcode
@country_code = country_code || I18n.locale.to_s.split("-")[1]
end
def valid?
GoingPostal.valid_postcode?(@postcode, @country_code)
end
def to_formatted_s
GoingPostal.format_postcode(@postcode, @country_code) || @postcode
end
def to_s
@postcode
end
end
require_relative '../../app/models/postal_code'
class PostcodeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless PostalCode.new(value).valid?
record.errors[attribute] << (options[:message] || "is not a valid postcode")
end
end
end
require 'fast_spec_helper'
require 'active_model'
require "validators/postcode_validator"
class TestModel
include ActiveModel::Validations
attr_accessor :value
validates :value, :postcode => true
def initialize(value=nil)
@value = value
end
end
describe PostcodeValidator do
let(:valid_uk_postcode) { "EC1Y1AA" }
let(:valid_au_postcode) { "3004" }
before(:all) do
@locale_before = I18n.locale
@enforce_available_before = I18n.enforce_available_locales
I18n.enforce_available_locales = false
end
after(:all) do
I18n.enforce_available_locales = @enforce_available_before
I18n.locale = @locale_before
end
context "when the locale includes a country code" do
before(:all) do
I18n.locale = "en-FOO"
end
it "should ask going postal to validate the postcode" do
GoingPostal.should_receive(:valid_postcode?).with("foo", anything)
TestModel.new("foo").valid?
end
it "should provide the country code to going postal" do
GoingPostal.should_receive(:valid_postcode?).with(anything, "FOO")
TestModel.new("foo").valid?
end
it "should be valid if going postal says it's valid" do
GoingPostal.stub(:valid_postcode?).and_return(true)
TestModel.new("foo").should be_valid
end
it "should not be valid if going postal says it's not valid" do
GoingPostal.stub(:valid_postcode?).and_return(false)
TestModel.new("foo").should_not be_valid
end
end
context "when the locale does not specify a country" do
before(:all) { I18n.locale = "en" }
it "should be valid for any value (e.g. foo)" do
TestModel.new("foo").should be_valid
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment