telephone_number 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6d1182623bbe38dba05f732f29020d92b4e3bf06
4
- data.tar.gz: b27bc63b6dd33e0310ee271a89e08d9b9a4c7e8e
3
+ metadata.gz: da8efdb23ca38191becf7d7a07a6387cce0530cf
4
+ data.tar.gz: 16577898ab4e8dccf7a85ed2bf0d2c2faa5a9a99
5
5
  SHA512:
6
- metadata.gz: 1c9df0dffe26550bfa71de2083dcaf9a8b45fa936a548e75f5fcf6c9cc7248016e366e1e3b38c3f9a8a74deae28b34b18c4dadd391c66ea83ebc723c7006ee8c
7
- data.tar.gz: c6f5876994fadb4cc44095e311548309703ffcec06ef5661512ab1fe9416340cea732b95b18d2230ea10dd754ef21c810d9dbf75c42febc79f09f302143073e6
6
+ metadata.gz: 3ec45bf229dcceaab6b9893dac3f96352789d45d7923e45551ace2e8fc92da1efcdf71adb2e50350f84783d66d247af666e2be24af78242e7ac9fceb323a2792
7
+ data.tar.gz: 3502e8e65b905792c767a6fda80865085eb3fd59d13857f7eb3e82c5e3d800615dbc7fc23c30cccb9ae9f8e44604f74939cde6f2f2dc7d5fe907678c1d64aa27
data/.rubocop.yml CHANGED
@@ -1,4 +1,9 @@
1
1
  inherit_from: .rubocop.default.yml
2
2
 
3
+ Metrics/AbcSize:
4
+ Enabled: false
5
+ Metrics/LineLength:
6
+ max: 120
3
7
  Style/StringLiterals:
4
8
  EnforcedStyle: single_quotes
9
+
data/README.md CHANGED
@@ -22,41 +22,90 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TelephoneNumber requires a country when parsing and validating phone numbers.
25
+ You can obtain a `TelephoneNumber` object by calling:
26
26
 
27
- **To validate a phone number:**
28
-
29
- TelephoneNumber.valid?("(555) 555-5555", "US") ==> false
30
-
31
- You can pass an optional array of keys to check the validity against.
32
-
33
- TelephoneNumber.valid?("(555) 555-5555", "US", [:mobile, :fixed_line]) ==> false
34
-
35
- **To parse a phone number:**
36
-
37
- TelephoneNumber.parse("(317) 508-3348", "US") ==>
38
-
39
- #<TelephoneNumber::Number:0x007fe3bc146cf0
40
- @country="US",
41
- @e164_number="13175083348",
42
- @national_number="3175083348",
43
- @original_number="3175083348">
44
-
45
- **To fetch valid types:**
46
-
47
- TelephoneNumber.parse("(317) 508-3348", "US").valid_types ==> ["mobile", "fixed_line"]
48
-
49
- **To format nationally:**
50
-
51
- TelephoneNumber.parse("(317) 508-3348", "US").national_number ==> "(317) 508-3348"
52
- TelephoneNumber.parse("(317) 508-3348", "US").national_number(formatted: false) ==> "3175083348"
27
+ ```
28
+ phone_object = TelephoneNumber.parse("3175082237", :us) ==>
53
29
 
30
+ #<TelephoneNumber::Number:0x007fe3bc146cf0
31
+ @country=:US,
32
+ @e164_number="13175083348",
33
+ @national_number="3175083348",
34
+ @original_number="3175083348">
35
+ ```
36
+ After that you have the following instance methods available to you.
37
+
38
+ - ### `valid_types`
39
+
40
+ Returns all types that the number is considered valid for.
41
+
42
+ `phone_object.valid_types ==> [:fixed_line, :mobile, :toll_free]`
43
+
44
+ - ### `valid?`
45
+
46
+ Returns boolean value indicating whether or not `valid_types` is empty.
47
+
48
+ `phone_object.valid? ==> true`
49
+
50
+ - ### `national_number(formatted: true)`
51
+
52
+ Returns the national formatted number including special characters such as parenthesis and dashes. You can omit the special characters by passing `formatted: false`
53
+
54
+ `phone_object.national_number ==> "(317) 508-2237"`
55
+
56
+ - ### `international_number(formatted: true)`
57
+
58
+ Returns the international formatted number including special characters such as parenthesis and dashes. You can omit the special characters by passing `formatted: false`
59
+
60
+ `phone_object.international_number ==> "+1 317-508-2237"`
61
+
62
+ - ### `e164_number(formatted: true)`
63
+
64
+ Returns the international formatted number including special characters such as parenthesis and dashes. You can omit the special characters by passing `formatted: false`
65
+
66
+ `phone_object.e164_number ==> "+13175082237"`
67
+
68
+ - ### `country`
69
+
70
+ Returns a symbol representation of the ISO 3166-1 alpha-2 for the country.
71
+
72
+ `phone_object.country ==> :US`
73
+
74
+ - ### `country_data`
75
+
76
+ Returns a symbolized hash of all data TelephoneNumber has about a number's particular country.
77
+
78
+ ### Class Methods
79
+
80
+ You also have the following class methods available to you.
81
+
82
+ - #### `parse`
83
+
84
+ Returns a TelephoneNumber object.
85
+
86
+ `TelephoneNumber.parse("3175082237", :US)`
87
+
88
+ - #### `valid?`
89
+
90
+ Returns boolean value indicating whether or not a particular number is valid.
91
+
92
+ `TelephoneNumber.valid?("3175082237", :US) ==> true`
93
+
94
+ - #### `invalid?`
95
+
96
+ Returns boolean value indicating whether or not a particular number is invalid.
97
+
98
+ `TelephoneNumber.invalid?("3175082237", :US) ==> false`
99
+
54
100
  ## Configuration
55
101
 
102
+ ### Override File
103
+
56
104
  In the event that you need to override the data that Google is providing, you can do so by setting an override file. This file is expected to be in the same format as Google's as well as serialized using Marshal.
57
105
 
58
106
  To generate a serialized override file:
59
107
 
108
+ ruby bin/console
60
109
  TelephoneNumber.generate_override_file("/path/to/file")
61
110
 
62
111
  In this instance, `/path/to/file` represents an xml file that has your custom data in the same structure that Google's data is in.
@@ -64,11 +113,24 @@ In this instance, `/path/to/file` represents an xml file that has your custom da
64
113
  You can set the override file with:
65
114
 
66
115
  TelephoneNumber.override_file = "/path/to_file.dat"
116
+
117
+ ### Default Number Pattern
67
118
 
119
+ If TelephoneNumber is passed an invalid number and then asked to format that number, it will simply return an unformatted string of the originally passed number. This is because formatting rules will not be found for invalid numbers. If this is unacceptable, you can set a `default_format_pattern` and `default_format_string` that TelephoneNumber will use attempt to format invalid numbers.
120
+
121
+ ```
122
+ TelephoneNumber.default_format_pattern = "(\\d{3})(\\d{3})(\\d*)"
123
+ TelephoneNumber.default_format_string = "($1) $2-$3"
124
+
125
+ invalid_number = "1111111111"
126
+ phone_object = TelephoneNumber.parse(invalid_number, :US)
127
+ phone_object.national_number ==> "(111) 111-1111"
128
+ ```
129
+
68
130
  ## Todo
69
131
 
70
132
  - Build custom validator to integrate with Rails
71
- - Build formatting functionality
133
+ - ~~Build formatting functionality~~
72
134
  - Build extended data functionality(short codes, carrier data, etc.)
73
135
 
74
136
  ## Development
data/Rakefile CHANGED
@@ -1,11 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
3
- require "telephone_number"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'telephone_number'
4
4
 
5
5
  Rake::TestTask.new(:test) do |t|
6
- t.libs << "test"
7
- t.libs << "lib"
6
+ t.libs << 'test'
7
+ t.libs << 'lib'
8
8
  t.test_files = FileList['test/**/*_test.rb']
9
+ t.warning = false
9
10
  end
10
11
 
11
12
  task :default => :test
@@ -13,7 +14,7 @@ task :default => :test
13
14
  namespace :data do
14
15
  namespace :main do
15
16
  task :import do
16
- TelephoneNumber::DataImporter.new(File.expand_path("data/telephone_number_data_file.xml")).import!
17
+ TelephoneNumber::DataImporter.new(File.expand_path('data/telephone_number_data_file.xml')).import!
17
18
  end
18
19
  end
19
20
 
data/bin/console CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "telephone_number"
3
+ require 'bundler/setup'
4
+ require 'telephone_number'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- require "pry"
10
+ require 'pry'
11
11
  Pry.start
12
12
 
@@ -1,4 +1,5 @@
1
- require "telephone_number/version"
1
+ require 'telephone_number/version'
2
+ require 'utilities/hash'
2
3
 
3
4
  module TelephoneNumber
4
5
  autoload :DataImporter, 'telephone_number/data_importer'
@@ -22,6 +23,29 @@ module TelephoneNumber
22
23
  @@override_file
23
24
  end
24
25
 
26
+ # allows users to provide a default format string
27
+ @@default_format_string = nil
28
+
29
+ def self.default_format_string=(format_string)
30
+ @@default_format_string = format_string
31
+ end
32
+
33
+ def self.default_format_string
34
+ @@default_format_string
35
+ end
36
+
37
+ # allows users to provide a default format pattern
38
+ @@default_format_pattern = nil
39
+
40
+ def self.default_format_pattern=(format_string)
41
+ @@default_format_pattern = Regexp.new(format_string)
42
+ end
43
+
44
+ def self.default_format_pattern
45
+ @@default_format_pattern
46
+ end
47
+
48
+
25
49
  # generates binary file from xml that user gives us
26
50
  def self.generate_override_file(file)
27
51
  DataImporter.new(file).import!(override: true)
@@ -5,7 +5,7 @@ module TelephoneNumber
5
5
 
6
6
  def initialize(file_name)
7
7
  @data = {}
8
- @file = File.open(file_name){ |f| Nokogiri::XML(f) }
8
+ @file = File.open(file_name) { |f| Nokogiri::XML(f) }
9
9
  end
10
10
 
11
11
  def import!(override: false)
@@ -14,8 +14,8 @@ module TelephoneNumber
14
14
  end
15
15
 
16
16
  def parse_main_data
17
- file.css("territories territory").each do |territory|
18
- country_code = territory.attributes["id"].value.to_sym
17
+ file.css('territories territory').each do |territory|
18
+ country_code = territory.attributes['id'].value.to_sym
19
19
  @data[country_code] ||= {}
20
20
 
21
21
  load_base_attributes(@data[country_code], territory)
@@ -28,15 +28,15 @@ module TelephoneNumber
28
28
  private
29
29
 
30
30
  def load_formats(country_data, territory)
31
- country_data[PhoneData::FORMATS] = territory.css("availableFormats numberFormat").map do |format|
32
- format_hash = {}.tap do |fhash|
31
+ country_data[PhoneData::FORMATS] = territory.css('availableFormats numberFormat').map do |format|
32
+ {}.tap do |fhash|
33
33
  format.attributes.values.each do |attr|
34
34
  key = underscore(attr.name).to_sym
35
35
  fhash[key] = if key == PhoneData::NATIONAL_PREFIX_FORMATTING_RULE
36
- attr.value
37
- else
38
- attr.value.delete("\n ")
39
- end
36
+ attr.value
37
+ else
38
+ attr.value.delete("\n ")
39
+ end
40
40
  end
41
41
  format.elements.each do |child|
42
42
  key = underscore(child.name).to_sym
@@ -49,9 +49,9 @@ module TelephoneNumber
49
49
  def load_validations(country_data, territory)
50
50
  country_data[PhoneData::VALIDATIONS] = {}
51
51
  territory.elements.each do |element|
52
- next if element.name == "references" || element.name == "availableFormats"
52
+ next if element.name == 'references' || element.name == 'availableFormats'
53
53
  country_data[PhoneData::VALIDATIONS][underscore(element.name).to_sym] = {}.tap do |validation_hash|
54
- element.elements.each{|child| validation_hash[underscore(child.name).to_sym] = child.text.delete("\n ")}
54
+ element.elements.each { |child| validation_hash[underscore(child.name).to_sym] = child.text.delete("\n ") }
55
55
  end
56
56
  end
57
57
  end
@@ -59,7 +59,7 @@ module TelephoneNumber
59
59
  def load_base_attributes(country_data, territory)
60
60
  territory.attributes.each do |key, value_object|
61
61
  underscored_key = underscore(key).to_sym
62
- country_data[underscored_key] = if underscored_key == PhoneData::NATIONAL_PREFIX_FOR_PARSING
62
+ country_data[underscored_key] = if underscored_key == PhoneData::NATIONAL_PREFIX_FOR_PARSING
63
63
  value_object.value.delete("\n ")
64
64
  else
65
65
  value_object.value
@@ -68,21 +68,21 @@ module TelephoneNumber
68
68
  end
69
69
 
70
70
  def load_references(country_data, territory)
71
- country_data[:references] = territory.css("references sourceUrl").map(&:text)
71
+ country_data[:references] = territory.css('references sourceUrl').map(&:text)
72
72
  end
73
73
 
74
74
  def underscore(camel_cased_word)
75
75
  return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/
76
76
  word = camel_cased_word.to_s.gsub(/::/, '/')
77
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
78
- word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
79
- word.tr!("-", "_")
77
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
78
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
79
+ word.tr!('-', '_')
80
80
  word.downcase!
81
81
  word
82
82
  end
83
83
 
84
84
  def save_data_file(override: false)
85
- data_file = override ? "telephone_number_data_override_file.dat" : "#{File.dirname(__FILE__)}/../../data/telephone_number_data_file.dat"
85
+ data_file = override ? 'telephone_number_data_override_file.dat' : "#{File.dirname(__FILE__)}/../../data/telephone_number_data_file.dat"
86
86
  File.open(data_file, 'wb+') { |f| Marshal.dump(@data, f) }
87
87
  end
88
88
  end
@@ -1,13 +1,13 @@
1
1
  module TelephoneNumber
2
2
  module Formatter
3
3
  def build_national_number(formatted: true)
4
- return normalized_number if !valid? || format.nil?
5
- captures = normalized_number.match(Regexp.new(format[PhoneData::PATTERN])).captures
6
- national_prefix_formatting_rule = format[PhoneData::NATIONAL_PREFIX_FORMATTING_RULE] \
4
+ return normalized_or_default if !valid? || number_format.nil?
5
+ captures = normalized_number.match(Regexp.new(number_format[PhoneData::PATTERN])).captures
6
+ national_prefix_formatting_rule = number_format[PhoneData::NATIONAL_PREFIX_FORMATTING_RULE] \
7
7
  || country_data[PhoneData::NATIONAL_PREFIX_FORMATTING_RULE]
8
8
 
9
- format_string = format[PhoneData::FORMAT].gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
10
- formatted_string = sprintf(format_string, *captures)
9
+ format_string = number_format[PhoneData::FORMAT].gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
10
+ formatted_string = format(format_string, *captures)
11
11
  captures.delete(PhoneData::MOBILE_TOKEN_COUNTRIES[country])
12
12
 
13
13
  if national_prefix_formatting_rule
@@ -26,21 +26,29 @@ module TelephoneNumber
26
26
  end
27
27
 
28
28
  def build_international_number(formatted: true)
29
- return normalized_number if !valid? || format.nil?
30
- captures = normalized_number.match(Regexp.new(format[PhoneData::PATTERN])).captures
31
- key = format.fetch(PhoneData::INTL_FORMAT, 'NA') != 'NA' ? PhoneData::INTL_FORMAT : PhoneData::FORMAT
32
- format_string = format[key].gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
33
- "+#{country_data[PhoneData::COUNTRY_CODE]} #{sprintf(format_string, *captures)}"
29
+ return normalized_or_default if !valid? || number_format.nil?
30
+ captures = normalized_number.match(Regexp.new(number_format[PhoneData::PATTERN])).captures
31
+ key = number_format.fetch(PhoneData::INTL_FORMAT, 'NA') != 'NA' ? PhoneData::INTL_FORMAT : PhoneData::FORMAT
32
+ format_string = number_format[key].gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
33
+ formatted_string = "+#{country_data[PhoneData::COUNTRY_CODE]} #{format(format_string, *captures)}"
34
+ formatted ? formatted_string : sanitize(formatted_string)
34
35
  end
35
36
 
36
37
  private
37
38
 
38
- def extract_format
39
+ def normalized_or_default
40
+ return normalized_number if !TelephoneNumber.default_format_string || !TelephoneNumber.default_format_pattern
41
+ captures = normalized_number.match(TelephoneNumber.default_format_pattern).captures
42
+ format_string = TelephoneNumber.default_format_string.gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
43
+ format(format_string, *captures)
44
+ end
45
+
46
+ def extract_number_format
39
47
  native_country_format = detect_format(country.to_sym)
40
48
  return native_country_format if native_country_format
41
49
 
42
50
  # This means we couldn't find an applicable format so we now need to scan through the hierarchy
43
- parent_country_code = PhoneData.phone_data.detect do |country_code, country_data|
51
+ parent_country_code = PhoneData.phone_data.detect do |_country_code, country_data|
44
52
  country_data[PhoneData::COUNTRY_CODE] == PhoneData.phone_data[self.country.to_sym][PhoneData::COUNTRY_CODE] \
45
53
  && country_data[PhoneData::MAIN_COUNTRY_FOR_CODE] == 'true'
46
54
  end
@@ -52,8 +52,8 @@ module TelephoneNumber
52
52
 
53
53
  private
54
54
 
55
- def format
56
- @format ||= extract_format
55
+ def number_format
56
+ @number_format ||= extract_number_format
57
57
  end
58
58
  end
59
59
  end
@@ -3,14 +3,14 @@ module TelephoneNumber
3
3
  KEYS_TO_SKIP = [PhoneData::GENERAL, PhoneData::AREA_CODE_OPTIONAL]
4
4
 
5
5
  def sanitize(input_number)
6
- return input_number.gsub(/[^0-9]/, "")
6
+ return input_number.gsub(/[^0-9]/, '')
7
7
  end
8
8
 
9
9
  # returns an array of valid types for the normalized number
10
10
  # if array is empty, we can assume that the number is invalid
11
11
  def validate
12
12
  return [] unless country_data
13
- applicable_keys = country_data[PhoneData::VALIDATIONS].reject{ |key, _value| KEYS_TO_SKIP.include?(key) }
13
+ applicable_keys = country_data[PhoneData::VALIDATIONS].reject { |key, _value| KEYS_TO_SKIP.include?(key) }
14
14
  applicable_keys.map do |phone_type, validations|
15
15
  full = "^(#{validations[PhoneData::VALID_PATTERN]})$"
16
16
  phone_type.to_sym if normalized_number =~ Regexp.new(full)
@@ -25,7 +25,7 @@ module TelephoneNumber
25
25
 
26
26
  number_with_correct_prefix = parse_prefix
27
27
 
28
- reg_string = "^(#{country_code})?"
28
+ reg_string = "^(#{country_code})?"
29
29
  reg_string << "(#{country_data[PhoneData::NATIONAL_PREFIX]})?"
30
30
  reg_string << "(#{country_data[PhoneData::VALIDATIONS][PhoneData::GENERAL][PhoneData::VALID_PATTERN]})$"
31
31
 
@@ -53,16 +53,16 @@ module TelephoneNumber
53
53
 
54
54
  def transform_national_prefix(duped, match_object)
55
55
  if PhoneData::MOBILE_TOKEN_COUNTRIES.include?(country) && match_object.captures.any?
56
- sprintf(build_format_string, duped.sub!(match_object[0], match_object[1]))
56
+ format(build_format_string, duped.sub!(match_object[0], match_object[1]))
57
57
  elsif match_object.captures.none?
58
58
  duped.sub!(match_object[0], '')
59
59
  else
60
- sprintf(build_format_string, *match_object.captures)
60
+ format(build_format_string, *match_object.captures)
61
61
  end
62
62
  end
63
63
 
64
64
  def build_format_string
65
- country_data[:national_prefix_transform_rule].gsub(/(\$\d)/) {|cap| "%#{cap.reverse}s"}
65
+ country_data[:national_prefix_transform_rule].gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
66
66
  end
67
67
  end
68
68
  end
@@ -1,32 +1,32 @@
1
1
  module TelephoneNumber
2
2
  module PhoneData
3
- AREA_CODE_OPTIONAL = :area_code_optional.freeze
4
- COUNTRY_CODE = :country_code.freeze
5
- FIXED_LINE = :fixed_line.freeze
6
- FORMATS = :formats.freeze
7
- FORMAT = :format.freeze
8
- GENERAL = :general_desc.freeze
9
- INTERNATIONAL_PREFIX = :international_prefix.freeze
10
- INTL_FORMAT = :intl_format.freeze
11
- LEADING_DIGITS = :leading_digits.freeze
12
- MAIN_COUNTRY_FOR_CODE = :main_country_for_code.freeze
13
- MOBILE = :mobile.freeze
3
+ AREA_CODE_OPTIONAL = :area_code_optional
4
+ COUNTRY_CODE = :country_code
5
+ FIXED_LINE = :fixed_line
6
+ FORMATS = :formats
7
+ FORMAT = :format
8
+ GENERAL = :general_desc
9
+ INTERNATIONAL_PREFIX = :international_prefix
10
+ INTL_FORMAT = :intl_format
11
+ LEADING_DIGITS = :leading_digits
12
+ MAIN_COUNTRY_FOR_CODE = :main_country_for_code
13
+ MOBILE = :mobile
14
14
  MOBILE_TOKEN_COUNTRIES = { AR: '9' }.freeze
15
- NATIONAL_PREFIX = :national_prefix.freeze
16
- NATIONAL_PREFIX_FOR_PARSING = :national_prefix_for_parsing.freeze
17
- NATIONAL_PREFIX_FORMATTING_RULE = :national_prefix_formatting_rule.freeze
18
- NO_INTERNATIONAL_DIALING = :no_international_dialling.freeze
15
+ NATIONAL_PREFIX = :national_prefix
16
+ NATIONAL_PREFIX_FOR_PARSING = :national_prefix_for_parsing
17
+ NATIONAL_PREFIX_FORMATTING_RULE = :national_prefix_formatting_rule
18
+ NO_INTERNATIONAL_DIALING = :no_international_dialling
19
19
  PATTERN = :pattern
20
- PERSONAL_NUMBER = :personal_number.freeze
21
- POSSIBLE_PATTERN = :possible_number_pattern.freeze
22
- PREMIUM_RATE = :premium_rate.freeze
23
- SHARED_COST = :shared_cost.freeze
24
- TOLL_FREE = :toll_free.freeze
25
- UAN = :uan.freeze
26
- VALIDATIONS = :validations.freeze
27
- VALID_PATTERN = :national_number_pattern.freeze
28
- VOICEMAIL = :voicemail.freeze
29
- VOIP = :voip.freeze
20
+ PERSONAL_NUMBER = :personal_number
21
+ POSSIBLE_PATTERN = :possible_number_pattern
22
+ PREMIUM_RATE = :premium_rate
23
+ SHARED_COST = :shared_cost
24
+ TOLL_FREE = :toll_free
25
+ UAN = :uan
26
+ VALIDATIONS = :validations
27
+ VALID_PATTERN = :national_number_pattern
28
+ VOICEMAIL = :voicemail
29
+ VOIP = :voip
30
30
 
31
31
  def self.phone_data
32
32
  @@phone_data ||= load_data
@@ -37,7 +37,7 @@ module TelephoneNumber
37
37
  main_data = Marshal.load(File.binread(data_file))
38
38
  override_data = {}
39
39
  override_data = Marshal.load(File.binread(TelephoneNumber.override_file)) if TelephoneNumber.override_file
40
- return main_data.merge!(override_data)
40
+ return main_data.deep_deep_merge!(override_data)
41
41
  end
42
42
  end
43
43
  end
@@ -50,7 +50,7 @@ module TelephoneNumber
50
50
  output_hash[key] = {}
51
51
 
52
52
  value.each_with_index do |num, counter|
53
- page = HTTParty.get(sprintf(URL, num, key.to_s))
53
+ page = HTTParty.get(format(URL, num, key.to_s))
54
54
  parsed_page = Nokogiri::HTML.parse(page)
55
55
  body = parsed_page.elements.first.elements.css('body').first
56
56
  parsed_data = parse_remote_data(counter, body.elements.css('table')[2])
@@ -1,3 +1,3 @@
1
1
  module TelephoneNumber
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -0,0 +1,38 @@
1
+ class Hash
2
+ # Returns a new hash with +self+ and +other_hash+ merged recursively.
3
+ #
4
+ # h1 = { a: true, b: { c: [1, 2, 3] } }
5
+ # h2 = { a: false, b: { x: [3, 4, 5] } }
6
+ #
7
+ # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
8
+ #
9
+ # Like with Hash#merge in the standard library, a block can be provided
10
+ # to merge values:
11
+ #
12
+ # h1 = { a: 100, b: 200, c: { c1: 100 } }
13
+ # h2 = { b: 250, c: { c1: 200 } }
14
+ # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
15
+ # # => { a: 100, b: 450, c: { c1: 300 } }
16
+ def deep_deep_merge(other_hash, &block)
17
+ dup.deep_deep_merge!(other_hash, &block)
18
+ end
19
+
20
+ # Same as +deep_merge+, but modifies +self+.
21
+ def deep_deep_merge!(other_hash, &block)
22
+ other_hash.each_pair do |current_key, other_value|
23
+ this_value = self[current_key]
24
+
25
+ self[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
26
+ this_value.deep_deep_merge(other_value, &block)
27
+ else
28
+ if block_given? && key?(current_key)
29
+ block.call(current_key, this_value, other_value)
30
+ else
31
+ other_value
32
+ end
33
+ end
34
+ end
35
+
36
+ self
37
+ end
38
+ end
@@ -4,29 +4,29 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'telephone_number/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "telephone_number"
7
+ spec.name = 'telephone_number'
8
8
  spec.version = TelephoneNumber::VERSION
9
9
  spec.author = 'MOBI Wireless Management'
10
- spec.email = ["adam.fernung@mobiwm.com", "josh.wetzel@mobiwm.com"]
10
+ spec.email = ['adam.fernung@mobiwm.com', 'josh.wetzel@mobiwm.com']
11
11
  spec.summary = 'Phone number validation'
12
- spec.homepage = "https://github.com/mobi/telephone_number"
13
- spec.license = "MIT"
12
+ spec.homepage = 'https://github.com/mobi/telephone_number'
13
+ spec.license = 'MIT'
14
14
 
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
17
  f.match(%r{^(test|spec|features)/})
18
18
  end
19
- spec.bindir = "exe"
19
+ spec.bindir = 'exe'
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
- spec.require_paths = ["lib"]
21
+ spec.require_paths = ['lib']
22
22
 
23
- spec.add_development_dependency "bundler"
24
- spec.add_development_dependency "rake"
25
- spec.add_development_dependency "minitest"
26
- spec.add_development_dependency "pry"
27
- spec.add_development_dependency "pry-byebug"
28
- spec.add_development_dependency "nokogiri"
29
- spec.add_development_dependency "httparty"
30
- spec.add_development_dependency "minitest-focus"
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'minitest'
26
+ spec.add_development_dependency 'pry'
27
+ spec.add_development_dependency 'pry-byebug'
28
+ spec.add_development_dependency 'nokogiri'
29
+ spec.add_development_dependency 'httparty'
30
+ spec.add_development_dependency 'minitest-focus'
31
31
  spec.add_development_dependency 'coveralls'
32
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: telephone_number
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MOBI Wireless Management
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-01 00:00:00.000000000 Z
11
+ date: 2017-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -168,6 +168,7 @@ files:
168
168
  - lib/telephone_number/phone_data.rb
169
169
  - lib/telephone_number/test_data_generator.rb
170
170
  - lib/telephone_number/version.rb
171
+ - lib/utilities/hash.rb
171
172
  - telephone_number.gemspec
172
173
  homepage: https://github.com/mobi/telephone_number
173
174
  licenses: