Created
June 27, 2011 14:42
-
-
Save rogerrohrbach/1048992 to your computer and use it in GitHub Desktop.
Active Model North American Telephone Number validator
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
# == Active Model North American Telephone Number Validator | |
# http://en.wikipedia.org/wiki/North_American_Numbering_Plan#Current_system | |
# [Author] Roger Rohrbach ([email protected]) | |
class NanpValidator < ActiveModel::EachValidator | |
def self.matcher(require_area_code) # :nodoc: | |
%r{ | |
(?<country_code> \+1 ){0} | |
(?<trunk_prefix> 1 ){0} | |
(?<delimiter> ([-\.]|\ +) ){0} | |
(?<area_code> [2-9]\d{2} ){0} | |
(?<exchange> [2-9]([02-9][0-9]|1[02-9]) ){0} | |
(?<station> \d{4} ){0} | |
^ | |
\ * | |
((\g<country_code>|\g<trunk_prefix>)\g<delimiter>{0,1})* | |
(\(*\g<area_code>\)*){#{require_area_code ? '1' : '0,1'}} | |
\g<delimiter>{0,1} | |
\g<exchange> | |
\g<delimiter>{0,1} | |
\g<station> | |
\ * | |
$ | |
}x | |
end | |
private_class_method :matcher | |
# <p><p> | |
# Validates a telephone number in the North American Numbering Plan. | |
# <p> | |
# Example: | |
# <p> | |
# class Person < ActiveRecord::Base | |
# validates :phone, :nanp => true | |
# end | |
# <p><p> | |
# Options: | |
# <p> | |
# * +require_area_code+ - | |
# consider number valid only if area code is present | |
# (default: +true+) | |
# | |
# * +allow_fictitious_numbers+ - | |
# allow numbers of the form 555-01<i>xx</i> or | |
# those with area code "958" (default: +false+) | |
# <p><p> | |
# e.g.: | |
# <p> | |
# class Person < ActiveRecord::Base | |
# validates :phone, :nanp => {require_area_code: false} | |
# end | |
def validate_each(record, attribute, value) | |
match = self.class.send( | |
:matcher, | |
({:require_area_code => true}.merge(options))[:require_area_code] | |
).match(value) | |
if match | |
if ["950", "958", "959", "976"].include?(match[:exchange]) | |
record.errors[attribute] << "is not a subscriber number" | |
end | |
# http://en.wikipedia.org/wiki/Fictitious_telephone_number | |
unless options[:allow_fictitious_numbers] | |
if match[:area_code] == "958" || | |
(match[:exchange] == "555" && match[:station] =~ /^01\d{2}$/) | |
record.errors[attribute] << "is fictitious" | |
end | |
end | |
else | |
record.errors[attribute] << "is not valid" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment