Skip to content

Instantly share code, notes, and snippets.

@harlow harlow/user.rb
Last active Dec 21, 2018

Embed
What would you like to do?
Extract a validator in Rails. Zip code validation.
# app/models/user.rb
class User < ActiveRecord::Base
validates :zip_code, presence: true, zip_code: true
end
# app/validators/zip_code_validator.rb
class ZipCodeValidator < ActiveModel::EachValidator
ZIP_CODE_REGEX = /^\d{5}(-\d{4})?$/
def validate_each(record, attribute, value)
unless ZIP_CODE_REGEX.match value
record.errors.add(attribute, "#{value} is not a valid zip code")
end
end
end
# spec/validators/zip_code_validator_spec.rb
require 'spec_helper'
describe ZipCodeValidator, '#validate_each' do
it 'does not add errors with a valid zip code' do
record = build_record('93108')
ZipCodeValidator.new(attributes: :zip_code).validate(record)
record.errors.should be_empty
end
it 'adds errors with an invalid zip code' do
record = build_record('invalid_zip')
ZipCodeValidator.new(attributes: :zip_code).validate(record)
record.errors.full_messages.should eq [
'Zip code invalid_zip is not a valid zip code'
]
end
def build_record(zip_code)
test_class.new.tap do |object|
object.zip_code = zip_code
end
end
def test_class
Class.new do
include ActiveModel::Validations
attr_accessor :zip_code
def self.name
'TestClass'
end
end
end
end
@dgilperez

This comment has been minimized.

Copy link

commented Aug 14, 2013

Hi!

Thanks for sharing :)

I'm generalizing the Validator to support different countries. Check it out if you want: https://gist.github.com/dgilperez/6232901

Cheers!

@scottbartell

This comment has been minimized.

Copy link

commented Apr 14, 2014

You should use \A and \z as anchors in your regex. http://stackoverflow.com/a/3632051

@dgilperez

This comment has been minimized.

Copy link

commented Sep 27, 2014

Hey!

I ended up pulling some bits together into this gem: validates_zipcode.

It currently supports 159 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

Cheers!

@ACPK

This comment has been minimized.

Copy link

commented Dec 3, 2015

@dgilperez @harlow - This validator doesn't seem to work if you're using "presence: false". I might recommend using "unless PHONE_REGEX.match(value) || value.blank?" so that a developer can use the presence attribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.