Skip to content

Commit

Permalink
[Enhancement] Support for extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Lee Squires authored and carr committed Jul 4, 2010
1 parent 7c34d55 commit 714590c
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 12 deletions.
10 changes: 6 additions & 4 deletions Readme.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ Or as a Rails plugin
script/plugin install git://github.com/carr/phone.git

== Initializing
You can initialize a new phone object with the number, area code and country code.
You can initialize a new phone object with the number, area code, country code and extension number

Phone.new('5125486', '91', '385')
or
Phone.new(:number => '5125486', :area_code => '91', :country_code => '385')
Phone.new(:number => '5125486', :area_code => '91', :country_code => '385', :extension => '143')

== Parsing
You can create a new phone object by parsing from a string. Phone does it's best to detect the country and area codes:
Expand Down Expand Up @@ -61,8 +61,9 @@ When given a string, it interpolates the string with the following fields:
* %a - area_code (91)
* %A - area_code with leading zero (091)
* %n - number (5125486)
* %n1 - first @@n1_length characters of number (configured through Phone.n1_length), default is 3 (512)
* %n2 - last characters of number (5486)
* %f - first @@n1_length characters of number (configured through Phone.n1_length), default is 3 (512)
* %l - last characters of number (5486)
* %x - the extension number

pn = Phone.parse('+385915125486')
pn.to_s # => "+385915125486"
Expand All @@ -72,6 +73,7 @@ When given a string, it interpolates the string with the following fields:
When given a symbol it is used as a lookup for the format in the <tt>Phone.named_formats</tt> hash.
pn.format(:europe) # => "+385 (0) 91 512 5486"
pn.format(:us) # => "(234) 123 4567"
pn.format(:default_with_extension) # => "+3851234567x143"

You can add your own custom named formats like so:
Phone.named_formats[:short] = '%A/%n1-%n2'
Expand Down
48 changes: 40 additions & 8 deletions lib/phone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Phone
NUMBER = '([^0][0-9]{1,7})$'
DEFAULT_AREA_CODE = '[2-9][0-8][0-9]' # USA

attr_accessor :country_code, :area_code, :number
attr_accessor :country_code, :area_code, :number, :extension

cattr_accessor :default_country_code
cattr_accessor :default_area_code
Expand All @@ -28,21 +28,23 @@ class Phone

@@named_formats = {
:default => "+%c%a%n",
:default_with_extension => "+%c%a%nx%x",
:europe => '+%c (0) %a %f %l',
:us => "(%a) %f-%l"
}

def initialize(*hash_or_args)
if hash_or_args.first.is_a?(Hash)
hash_or_args = hash_or_args.first
keys = {:number => :number, :area_code => :area_code, :country_code => :country_code}
keys = {:number => :number, :area_code => :area_code, :country_code => :country_code, :extension => :extension}
else
keys = {:number => 0, :area_code => 1, :country_code => 2}
keys = {:number => 0, :area_code => 1, :country_code => 2, :extension => 3}
end

self.number = hash_or_args[ keys[:number] ]
self.area_code = hash_or_args[ keys[:area_code] ] || self.default_area_code
self.country_code = hash_or_args[ keys[:country_code] ] || self.default_country_code
self.extension = hash_or_args[ keys[:extension] ]

raise "Must enter number" if self.number.blank?
raise "Must enter area code or set default area code" if self.area_code.blank?
Expand All @@ -54,6 +56,7 @@ def initialize(*hash_or_args)
def self.parse(string, options={})
if string.present?
PhoneCountry.load
extension = extract_extension(string)
string = normalize(string)

options[:country_code] ||= self.default_country_code
Expand All @@ -62,6 +65,10 @@ def self.parse(string, options={})
parts = split_to_parts(string, options)

pn = Phone.new(parts) if parts
if pn.present? and extension.present?
pn.extension = extension
end
return pn
end
end

Expand Down Expand Up @@ -150,7 +157,29 @@ def self.detect_format(string_with_number, country)
def self.normalize(string_with_number)
string_with_number.gsub("(0)", "").gsub(/[^0-9+]/, '').gsub(/^00/, '+')
end


# pull off anything that look like an extension
#TODO: refactor things so this doesn't change string as a side effect
#
def self.extract_extension(string)
return nil if string.nil?
if string.sub! /[ ]*(ext|ex|x|xt|#|:)+[^0-9]*\(*([-0-9]{1,})\)*#?$/i, ''
extension = $2
return extension
end
#
# We already returned any recognizable extension.
# However, we might still have extra junk to the right
# of the phone number proper, so just chop it off.
#
idx = string.rindex(/[0-9]/)
return nil if idx.nil?
return nil if idx == (string.length - 1) # at the end
string.slice!((idx+1)..-1) # chop it
return nil
end

# format area_code with trailing zero (e.g. 91 as 091)
# format area_code with trailing zero (e.g. 91 as 091)
def area_code_long
"0" + area_code if area_code
Expand All @@ -175,8 +204,9 @@ def number2
# * %a - area_code (91)
# * %A - area_code with leading zero (091)
# * %n - number (5125486)
# * %n1 - first @@n1_length characters of number (configured through Phone.n1_length), default is 3 (512)
# * %n2 - last characters of number (5486)
# * %f - first @@n1_length characters of number (configured through Phone.n1_length), default is 3 (512)
# * %l - last characters of number (5486)
# * %x - entire extension
#
# if the method argument is a Symbol, it is used as a lookup key for a format String in Phone.named_formats
# pn.format(:europe)
Expand Down Expand Up @@ -207,11 +237,13 @@ def has_default_area_code?
private

def format_number(fmt)
fmt.gsub("%c", country_code || "").
result = fmt.gsub("%c", country_code || "").
gsub("%a", area_code || "").
gsub("%A", area_code_long || "").
gsub("%n", number || "").
gsub("%f", number1 || "").
gsub("%l", number2 || "")
gsub("%l", number2 || "").
gsub("%x", extension || "")
return result
end
end
25 changes: 25 additions & 0 deletions test/extension_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require File.dirname(__FILE__) + '/test_helper'

class ExtensionTest < Test::Unit::TestCase

def test_parse_usa_long_with_simple_extension
pn = Phone.parse "+1 2069735100 x143"

assert_not_nil pn, %Q{parse should pass}
assert_equal '9735100', pn.number
assert_equal '206', pn.area_code
assert_equal '1', pn.country_code
assert_equal '143', pn.extension
end

def test_to_s_with_extension
pn = Phone.new '5125486', '91', '385', '143'
assert_equal '+385915125486x143', pn.format(:default_with_extension)
end

def test_format_with_extension
pn = Phone.new '5125486', '91', '385', '143'
assert_equal '(091)/512-5486 x 143', pn.format('(%A)/%f-%l x %x')
end

end
99 changes: 99 additions & 0 deletions test_usa_phones_with_extensions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
601-867-5000 ext 75292
(334)821-2223 Ext. 107
(863) 983-6171 ext: 0055
601-987-3995 ext 10
(512) 473-3200Ext2396
(727) 558-5010 ext: 0112
(904) 360-5611 ext: 5611
(937) 255-7204Ext337
228-374-5022 ext 5386
(205)987-3500 Ext. 205-32
(607) 273-8588x402
(205)328-3330 Ext. 802-59
(407) 251-2452 ext: 0146
502-564-8110 xt 312
(828) 698-3923x13
(608)836-7433 Ext. 5147
(1-808)935-3222 Ext. 2#
(770)420-3179 Ext. x 179
(415) 558-8669x218
(205)879-6330 Ext. 731-50
(205)987-5995 Ext. 802-58
(609) 924-2200Ext10
(312) 440-4373x12
(978) 369-9602x457
1-602-264-1774 # 135
502-564-8890 x4340
502-564-5550 x4569
(480)437-2600 Ext. VM123
(850) 245-4131 ext: 3506
601-354-6161 ext 103
(414)778-5400 Ext. 127
(262)338-4475 Ext. #16
(602) 264-1774 extention # 135
(314) 361-3221x107
(800) 255-5747x46
410-514-7336 TDDTTY + Voice
(617) 695-2300x393
1-334-386-8800 Ext. 107
(928)634-9536 Ext. 143
502-573-1555 x266
(978) 927-8000x246
(920) 887-4600Ext340
502-564-1404 x4536
(850) 245-6774 ext: 4774
(718) 852-3000 Ext 269
228-374-5022 ext 5022
502-564-0105 x10260
(850) 000-0000 ext: 00000000
(979) 233-1616x306
(207) 333-3267x224
(561) 625-5122 ext: 687
(386) 961-7414 ext: 7414
(262)549-2249 Ext. 104
(205)322-7500 Ext. BECKYS
(303)858-8100 Ext. n.a.
(937) 255-7204x337
601-944-4830 ext 104
228-432-1056 ext 104
(209) 586-1495Ext104
502-564-8139 : 4645
(602) 264-1774 ext is 135
(602) 264-1774Ext135
502-564-7822 x4212
(609) 921-8808Ext3
(703) 739-7900x222
(609) 758-2241x144
(970)223-6500 Ext. X6510
(734) 485-2000Ext255
(904) 620-4424 ext: 8614424
(904) 827-2520 ext: 2520
(978) 774-1050x251
(541) 343-0123x2269
(608)277-2752 Ext. 2752
(203) 869-6786x335
502-564-5981 x272
606-878-5908 x6085
502-564-2257 x3464
(205)871-1911 Ext. (205)
502-564-7770 x3965
(608)374-2130 Ext. 28
(850) 410-9660 ext: 9240
601-987-6837 ext 102
(414)529-1101 Ext. 153
(209) 586-1495x104
(520)408-1885 Ext. # 227
601-605-5388 ext 100
(352) 375-8484 ext: 0174
15025645981x225
(602) 264-1774 X 135
(205)803-1499 Ext. 414-03
(651) 459-4121x203
+61 3 9811 2400
(262)681-2020 Ext. 6682
601-944-4845 ext 118
384-1100 VOICE MAIL:3004
(205)251-1267 Ext. 802-09
(410) 280-2038Ext11
502-564-3170 x190
15025646734x4420

0 comments on commit 714590c

Please sign in to comment.