|
|
@@ -0,0 +1,77 @@ |
|
|
# == Active Model North American Telephone Number Validator |
|
|
# http://en.wikipedia.org/wiki/North_American_Numbering_Plan#Current_system |
|
|
# [Author] Roger Rohrbach (roger@ecstatic.com) |
|
|
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 |