Skip to content

Instantly share code, notes, and snippets.

@galetahub
Created July 1, 2011 10:16
Show Gist options
  • Save galetahub/1058239 to your computer and use it in GitHub Desktop.
Save galetahub/1058239 to your computer and use it in GitHub Desktop.
Phone numbers parser
# PhoneNumber parser
# Example:
# p = PhoneNumber.new('+380971265128')
# => #<PhoneNumber:0xb37b404 @value="380971265128", @locale=:uk, @pattern=[38, "097", ["126", "51", "28"]]>
# p.valid?
# => true
# p.to_s
# => "38 (097) 126-51-28"
# p.to_s(:prefix => true)
# => "+38 (097) 126-51-28"
# p.to_s(:format => "(%o) %n", :spliter => ' ')
# => "(097) 126 51 28"
# p.to_i
# => 380971265128
# PhoneNumber.new(380971265128).to_s(:prefix => true)
# => "+38 (097) 126-51-28"
#
# ActiveRecord
#
# composed_of :phone,
# :class_name => 'PhoneNumber',
# :mapping => %w(phone_number to_i)
#
class PhoneNumber
TABLE = {
:uk => {
:codes => %W( 039 050 063 066 067 068 091 092 093 094 095 096 097 098 099 ),
:regex => /^\+?(\d{0,2})(\d{3})(\d{3})(\d{2})(\d{2})$/,
:country => 38,
:format => "%c (%o) %n"
}
}
attr_accessor :locale, :value
def initialize(phone, options = {})
@value = phone.to_s.downcase.scan(/\d+/).join
@locale = (options[:locale] || I18n.locale).to_sym
@pattern = self.class.parse(@value, @locale)
end
# Check pattern, country and operator code
def valid?
@pattern && table[:country] == @pattern[0] && table[:codes].include?(@pattern[1])
end
# Creates a phone number based on pattern provided. Defaults to US (NANP) formatting (111) 111-1111.
#
# Symbols:
# %c - country code
# %o - operator
# %n - phone number
#
def to_s(options = {})
if valid?
options = { :prefix => false, :spliter => "-", :format => table[:format] }.merge(options)
str = (options[:prefix] ? "+" : '') + options[:format]
arr = [@pattern[0], @pattern[1], @pattern[2].join(options[:spliter])]
[ /%c/, /%o/, /%n/ ].each_with_index { |regex, index| str = str.gsub(regex, arr[index].to_s) }
str
end
end
def to_i
if valid?
@pattern.join.to_i
end
end
def table
TABLE[@locale]
end
# Parse phone number by given regex
# Return a array of parsed values (prefix, operator, phone number ...)
#
def self.parse(value, locale = nil)
locale ||= I18n.locale
table = TABLE[locale.to_sym]
if m = value.match( table[:regex] )
[ (m[1].blank? ? table[:country] : m[1]).to_i, m[2], m.to_a.slice(3..-1) ]
end
end
end
@g1smd
Copy link

g1smd commented Sep 2, 2012

Country code for Ukraine is +380 not +38.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment