Class: Phone
Constant Summary collapse
- NUMBER =
'([0-9]{1,8})$'- DEFAULT_AREA_CODE =
USA
'[2-9][0-8][0-9]'- @@n1_length =
default length of first number part
3- @@named_formats =
{ :default => "+%c%a%n", :default_with_extension => "+%c%a%nx%x", :europe => '+%c (0) %a %f %l', :us => "(%a) %f-%l" }
Instance Attribute Summary collapse
-
#area_code ⇒ Object
Returns the value of attribute area_code.
-
#country_code ⇒ Object
Returns the value of attribute country_code.
-
#extension ⇒ Object
Returns the value of attribute extension.
-
#number ⇒ Object
Returns the value of attribute number.
Class Method Summary collapse
-
.detect_country(string) ⇒ Object
detect country from the string entered.
-
.detect_format(string_with_number, country) ⇒ Object
detect format (from FORMATS) of input string.
-
.extract_extension(string) ⇒ Object
pull off anything that look like an extension TODO: refactor things so this doesn’t change string as a side effect.
- .formats(country) ⇒ Object
-
.normalize(string_with_number) ⇒ Object
fix string so it’s easier to parse, remove extra characters etc.
-
.parse(string, options = {}) ⇒ Object
create a new phone number by parsing a string the format of the string is detect automatically (from FORMATS).
-
.split_to_parts(string, options = {}) ⇒ Object
split string into hash with keys :country_code, :area_code and :number.
-
.valid?(string) ⇒ Boolean
is this string a valid phone number?.
Instance Method Summary collapse
-
#area_code_long ⇒ Object
format area_code with trailing zero (e.g. 91 as 091) format area_code with trailing zero (e.g. 91 as 091).
-
#format(fmt) ⇒ Object
Formats the phone number.
-
#has_default_area_code? ⇒ Boolean
does this number belong to the default area code?.
-
#has_default_country_code? ⇒ Boolean
does this number belong to the default country code?.
-
#initialize(*hash_or_args) ⇒ Phone
constructor
A new instance of Phone.
-
#number1 ⇒ Object
first n characters of :number.
-
#number2 ⇒ Object
everything left from number after the first n characters (see number1).
-
#to_s ⇒ Object
the default format is “+%c%a%n”.
Constructor Details
#initialize(*hash_or_args) ⇒ Phone
Returns a new instance of Phone.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/phone.rb', line 36 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, :extension => :extension} else 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? raise "Must enter country code or set default country code" if self.country_code.blank? end |
Instance Attribute Details
#area_code ⇒ Object
Returns the value of attribute area_code.
18 19 20 |
# File 'lib/phone.rb', line 18 def area_code @area_code end |
#country_code ⇒ Object
Returns the value of attribute country_code.
18 19 20 |
# File 'lib/phone.rb', line 18 def country_code @country_code end |
#extension ⇒ Object
Returns the value of attribute extension.
18 19 20 |
# File 'lib/phone.rb', line 18 def extension @extension end |
#number ⇒ Object
Returns the value of attribute number.
18 19 20 |
# File 'lib/phone.rb', line 18 def number @number end |
Class Method Details
.detect_country(string) ⇒ Object
detect country from the string entered
120 121 122 123 124 125 126 127 128 129 |
# File 'lib/phone.rb', line 120 def self.detect_country(string) detected_country = nil # find if the number has a country code PhoneCountry.all.each_pair do |country_code, country| if string =~ country.country_code_regexp detected_country = country end end detected_country end |
.detect_format(string_with_number, country) ⇒ Object
detect format (from FORMATS) of input string
142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/phone.rb', line 142 def self.detect_format(string_with_number, country) arr = [] formats(country).each_pair do |format, regexp| arr << format if string_with_number =~ regexp end # raise "Detected more than 1 format for #{string_with_number}" if arr.size > 1 if arr.length > 1 # puts %Q{detect_format: more than one format found - #{arr.inspect}} return :really_short end arr.first end |
.extract_extension(string) ⇒ Object
pull off anything that look like an extension TODO: refactor things so this doesn’t change string as a side effect
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/phone.rb', line 164 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 |
.formats(country) ⇒ Object
131 132 133 134 135 136 137 138 139 |
# File 'lib/phone.rb', line 131 def self.formats(country) area_code_regexp = country.area_code || DEFAULT_AREA_CODE { # 047451588, 013668734 :short => Regexp.new('^0?(' + area_code_regexp + ')' + NUMBER), # 451588 :really_short => Regexp.new('^' + NUMBER) } end |
.normalize(string_with_number) ⇒ Object
fix string so it’s easier to parse, remove extra characters etc.
157 158 159 |
# File 'lib/phone.rb', line 157 def self.normalize(string_with_number) string_with_number.gsub("(0)", "").gsub(/[^0-9+]/, '').gsub(/^00/, '+') end |
.parse(string, options = {}) ⇒ Object
create a new phone number by parsing a string the format of the string is detect automatically (from FORMATS)
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/phone.rb', line 56 def self.parse(string, ={}) if string.present? PhoneCountry.load extension = extract_extension(string) string = normalize(string) [:country_code] ||= self.default_country_code [:area_code] ||= self.default_area_code parts = split_to_parts(string, ) pn = Phone.new(parts) if parts if pn.present? and extension.present? pn.extension = extension end return pn end end |
.split_to_parts(string, options = {}) ⇒ Object
split string into hash with keys :country_code, :area_code and :number
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/phone.rb', line 85 def self.split_to_parts(string, = {}) country = detect_country(string) if country [:country_code] = country.country_code string = string.gsub(country.country_code_regexp, '0') else if [:country_code] country = PhoneCountry.find_by_country_code [:country_code] end end if country.nil? if [:country_code].nil? raise "Must enter country code or set default country code" else raise "Could not find country with country code #{[:country_code]}" end end format = detect_format(string, country) return nil if format.nil? parts = string.match formats(country)[format] case format when :short {:number => parts[2], :area_code => parts[1], :country_code => [:country_code]} when :really_short {:number => parts[1], :area_code => [:area_code], :country_code => [:country_code]} end end |
.valid?(string) ⇒ Boolean
is this string a valid phone number?
76 77 78 79 80 81 82 |
# File 'lib/phone.rb', line 76 def self.valid?(string) begin parse(string).present? rescue RuntimeError # if we encountered exceptions (missing country code, missing area code etc) return false end end |
Instance Method Details
#area_code_long ⇒ Object
format area_code with trailing zero (e.g. 91 as 091) format area_code with trailing zero (e.g. 91 as 091)
184 185 186 |
# File 'lib/phone.rb', line 184 def area_code_long "0" + area_code if area_code end |
#format(fmt) ⇒ Object
Formats the phone number.
if the method argument is a String, it is used as a format string, with the following fields being interpolated:
-
%c - country_code (385)
-
%a - area_code (91)
-
%A - area_code with leading zero (091)
-
%n - number (5125486)
-
%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)
213 214 215 216 217 218 219 220 |
# File 'lib/phone.rb', line 213 def format(fmt) if fmt.is_a?(Symbol) raise "The format #{fmt} doesn't exist'" unless named_formats.has_key?(fmt) format_number named_formats[fmt] else format_number(fmt) end end |
#has_default_area_code? ⇒ Boolean
does this number belong to the default area code?
233 234 235 |
# File 'lib/phone.rb', line 233 def has_default_area_code? area_code == self.class.default_area_code end |
#has_default_country_code? ⇒ Boolean
does this number belong to the default country code?
228 229 230 |
# File 'lib/phone.rb', line 228 def has_default_country_code? country_code == self.class.default_country_code end |
#number1 ⇒ Object
first n characters of :number
189 190 191 |
# File 'lib/phone.rb', line 189 def number1 number[0...self.class.n1_length] end |
#number2 ⇒ Object
everything left from number after the first n characters (see number1)
194 195 196 197 |
# File 'lib/phone.rb', line 194 def number2 n2_length = number.size - self.class.n1_length number[-n2_length, n2_length] end |
#to_s ⇒ Object
the default format is “+%c%a%n”
223 224 225 |
# File 'lib/phone.rb', line 223 def to_s format(:default) end |