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 +4 -4
- data/.rubocop.yml +5 -0
- data/README.md +90 -28
- data/Rakefile +7 -6
- data/bin/console +3 -3
- data/lib/telephone_number.rb +25 -1
- data/lib/telephone_number/data_importer.rb +17 -17
- data/lib/telephone_number/formatter.rb +20 -12
- data/lib/telephone_number/number.rb +2 -2
- data/lib/telephone_number/parser.rb +6 -6
- data/lib/telephone_number/phone_data.rb +26 -26
- data/lib/telephone_number/test_data_generator.rb +1 -1
- data/lib/telephone_number/version.rb +1 -1
- data/lib/utilities/hash.rb +38 -0
- data/telephone_number.gemspec +14 -14
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da8efdb23ca38191becf7d7a07a6387cce0530cf
|
4
|
+
data.tar.gz: 16577898ab4e8dccf7a85ed2bf0d2c2faa5a9a99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ec45bf229dcceaab6b9893dac3f96352789d45d7923e45551ace2e8fc92da1efcdf71adb2e50350f84783d66d247af666e2be24af78242e7ac9fceb323a2792
|
7
|
+
data.tar.gz: 3502e8e65b905792c767a6fda80865085eb3fd59d13857f7eb3e82c5e3d800615dbc7fc23c30cccb9ae9f8e44604f74939cde6f2f2dc7d5fe907678c1d64aa27
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -22,41 +22,90 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
You can obtain a `TelephoneNumber` object by calling:
|
26
26
|
|
27
|
-
|
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
|
2
|
-
require
|
3
|
-
require
|
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 <<
|
7
|
-
t.libs <<
|
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(
|
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
|
4
|
-
require
|
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
|
10
|
+
require 'pry'
|
11
11
|
Pry.start
|
12
12
|
|
data/lib/telephone_number.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
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(
|
18
|
-
country_code = territory.attributes[
|
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(
|
32
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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 ==
|
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
|
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(
|
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 ?
|
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
|
5
|
-
captures = normalized_number.match(Regexp.new(
|
6
|
-
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 =
|
10
|
-
formatted_string =
|
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
|
30
|
-
captures = normalized_number.match(Regexp.new(
|
31
|
-
key =
|
32
|
-
format_string =
|
33
|
-
"+#{country_data[PhoneData::COUNTRY_CODE]} #{
|
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
|
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 |
|
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
|
@@ -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
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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.
|
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(
|
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])
|
@@ -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
|
data/telephone_number.gemspec
CHANGED
@@ -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 =
|
7
|
+
spec.name = 'telephone_number'
|
8
8
|
spec.version = TelephoneNumber::VERSION
|
9
9
|
spec.author = 'MOBI Wireless Management'
|
10
|
-
spec.email = [
|
10
|
+
spec.email = ['adam.fernung@mobiwm.com', 'josh.wetzel@mobiwm.com']
|
11
11
|
spec.summary = 'Phone number validation'
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
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 =
|
19
|
+
spec.bindir = 'exe'
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
-
spec.require_paths = [
|
21
|
+
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
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.
|
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-
|
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:
|