Permalink
Browse files

[Enhancement] Support for extensions

  • Loading branch information...
1 parent 7c34d55 commit 714590c69cc01a7fa7192f6c1b8455178d6976f6 Michael Lee Squires committed with Jul 4, 2010
Showing with 170 additions and 12 deletions.
  1. +6 −4 Readme.rdoc
  2. +40 −8 lib/phone.rb
  3. +25 −0 test/extension_test.rb
  4. +99 −0 test_usa_phones_with_extensions.csv
View
@@ -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:
@@ -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"
@@ -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'
View
@@ -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
@@ -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?
@@ -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
@@ -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
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -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.