telephone_number 1.1.1 → 1.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/README.md +1 -1
- data/data/telephone_number_data_file.dat +0 -0
- data/data/telephone_number_data_file.xml +3534 -3406
- data/lib/active_model/telephone_number_validator.rb +9 -0
- data/lib/telephone_number/class_methods.rb +23 -3
- data/lib/telephone_number/country.rb +67 -0
- data/lib/telephone_number/data_importer.rb +7 -8
- data/lib/telephone_number/formatter.rb +27 -64
- data/lib/telephone_number/number.rb +5 -4
- data/lib/telephone_number/number_format.rb +14 -0
- data/lib/telephone_number/number_validation.rb +10 -0
- data/lib/telephone_number/parser.rb +22 -51
- data/lib/telephone_number/test_data_generator.rb +28 -3
- data/lib/telephone_number/version.rb +1 -1
- data/lib/telephone_number.rb +9 -40
- data/lib/utilities/hash.rb +9 -0
- data/telephone_number.gemspec +1 -1
- metadata +13 -10
- data/lib/telephone_number/phone_data.rb +0 -50
@@ -0,0 +1,9 @@
|
|
1
|
+
class TelephoneNumberValidator < ActiveModel::EachValidator
|
2
|
+
def validate_each(record, attribute, value)
|
3
|
+
country = options[:country].call(record) if options.key?(:country)
|
4
|
+
valid_types = options.fetch(:types, [])
|
5
|
+
args = [value, country, valid_types]
|
6
|
+
|
7
|
+
record.errors.add(attribute, :invalid) if TelephoneNumber.invalid?(*args)
|
8
|
+
end
|
9
|
+
end
|
@@ -1,10 +1,17 @@
|
|
1
1
|
module TelephoneNumber
|
2
2
|
module ClassMethods
|
3
|
-
|
4
|
-
|
3
|
+
attr_accessor :override_file, :default_format_string
|
4
|
+
attr_reader :default_format_pattern
|
5
|
+
|
6
|
+
def default_format_pattern=(format_string)
|
7
|
+
@default_format_pattern = Regexp.new(format_string)
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse(number, country = detect_country(number))
|
11
|
+
TelephoneNumber::Number.new(sanitize(number), country)
|
5
12
|
end
|
6
13
|
|
7
|
-
def valid?(number, country =
|
14
|
+
def valid?(number, country = detect_country(number), keys = [])
|
8
15
|
parse(number, country).valid?(keys)
|
9
16
|
end
|
10
17
|
|
@@ -12,6 +19,19 @@ module TelephoneNumber
|
|
12
19
|
!valid?(*args)
|
13
20
|
end
|
14
21
|
|
22
|
+
def sanitize(input_number)
|
23
|
+
input_number.to_s.gsub(/\D/, '')
|
24
|
+
end
|
25
|
+
|
26
|
+
def detect_country(number)
|
27
|
+
sanitized_number = sanitize(number)
|
28
|
+
detected_country = Country.all_countries.detect do |country|
|
29
|
+
sanitized_number.start_with?(country.country_code) && valid?(sanitized_number, country.country_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
detected_country.country_id.to_sym if detected_country
|
33
|
+
end
|
34
|
+
|
15
35
|
# generates binary file from xml that user gives us
|
16
36
|
def generate_override_file(file)
|
17
37
|
DataImporter.new(file, override: true).import!
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module TelephoneNumber
|
2
|
+
class Country
|
3
|
+
attr_reader :country_code, :national_prefix, :national_prefix_formatting_rule,
|
4
|
+
:national_prefix_for_parsing, :national_prefix_transform_rule, :international_prefix,
|
5
|
+
:formats, :validations, :mobile_token, :country_id, :general_validation, :main_country_for_code
|
6
|
+
|
7
|
+
MOBILE_TOKEN_COUNTRIES = { AR: '9' }
|
8
|
+
|
9
|
+
def initialize(data_hash)
|
10
|
+
@country_code = data_hash[:country_code]
|
11
|
+
@country_id = data_hash[:id]
|
12
|
+
@formats = data_hash.fetch(:formats, []).map { |format| NumberFormat.new(format) }
|
13
|
+
@general_validation = NumberValidation.new(:general_desc, data_hash[:validations][:general_desc]) if data_hash.fetch(:validations, {})[:general_desc]
|
14
|
+
@international_prefix = Regexp.new(data_hash[:international_prefix]) if data_hash[:international_prefix]
|
15
|
+
@main_country_for_code = data_hash[:main_country_for_code] == 'true'
|
16
|
+
@mobile_token = MOBILE_TOKEN_COUNTRIES[@country_id.to_sym]
|
17
|
+
@national_prefix = data_hash[:national_prefix]
|
18
|
+
@national_prefix_formatting_rule = data_hash[:national_prefix_formatting_rule]
|
19
|
+
@national_prefix_for_parsing = Regexp.new(data_hash[:national_prefix_for_parsing]) if data_hash[:national_prefix_for_parsing]
|
20
|
+
@national_prefix_transform_rule = data_hash[:national_prefix_transform_rule]
|
21
|
+
@validations = data_hash.fetch(:validations, {})
|
22
|
+
.except(:general_desc, :area_code_optional)
|
23
|
+
.map { |name, data| NumberValidation.new(name, data) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def detect_format(number)
|
27
|
+
native_format = formats.detect do |format|
|
28
|
+
number =~ Regexp.new("^(#{format.leading_digits})") && number =~ Regexp.new("^(#{format.pattern})$")
|
29
|
+
end
|
30
|
+
|
31
|
+
return native_format if native_format || main_country_for_code
|
32
|
+
parent_country.detect_format(number) if parent_country
|
33
|
+
end
|
34
|
+
|
35
|
+
def parent_country
|
36
|
+
return if main_country_for_code
|
37
|
+
Country.all_countries.detect do |country|
|
38
|
+
country.country_code == self.country_code && country.main_country_for_code
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def full_general_pattern
|
43
|
+
%r{^(#{country_code})?(#{national_prefix})?(?<national_num>#{general_validation.pattern})$}
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.phone_data
|
47
|
+
@phone_data ||= load_data
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.find(country_id)
|
51
|
+
data = phone_data[country_id.to_s.upcase.to_sym]
|
52
|
+
new(data) if data
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.load_data
|
56
|
+
data_file = "#{File.dirname(__FILE__)}/../../data/telephone_number_data_file.dat"
|
57
|
+
main_data = Marshal.load(File.binread(data_file))
|
58
|
+
override_data = {}
|
59
|
+
override_data = Marshal.load(File.binread(TelephoneNumber.override_file)) if TelephoneNumber.override_file
|
60
|
+
return main_data.deep_deep_merge!(override_data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.all_countries
|
64
|
+
@all_countries ||= phone_data.values.map {|data| new(data)}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -33,7 +33,7 @@ module TelephoneNumber
|
|
33
33
|
{}.tap do |fhash|
|
34
34
|
format.attributes.values.each do |attr|
|
35
35
|
key = underscore(attr.name).to_sym
|
36
|
-
fhash[key] = if key ==
|
36
|
+
fhash[key] = if key == :national_prefix_formatting_rule
|
37
37
|
attr.value
|
38
38
|
else
|
39
39
|
attr.value.delete("\n ")
|
@@ -41,30 +41,30 @@ module TelephoneNumber
|
|
41
41
|
end
|
42
42
|
format.elements.each do |child|
|
43
43
|
key = underscore(child.name).to_sym
|
44
|
-
fhash[key] = [
|
44
|
+
fhash[key] = [:format, :intl_format].include?(key) ? child.text : child.text.delete("\n ")
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
return if override && formats_arr.empty?
|
50
|
-
country_data[
|
50
|
+
country_data[:formats] = formats_arr
|
51
51
|
end
|
52
52
|
|
53
53
|
def load_validations(country_data, territory)
|
54
|
-
country_data[
|
54
|
+
country_data[:validations] = {}
|
55
55
|
territory.elements.each do |element|
|
56
56
|
next if element.name == 'references' || element.name == 'availableFormats'
|
57
|
-
country_data[
|
57
|
+
country_data[:validations][underscore(element.name).to_sym] = {}.tap do |validation_hash|
|
58
58
|
element.elements.each { |child| validation_hash[underscore(child.name).to_sym] = child.text.delete("\n ") }
|
59
59
|
end
|
60
60
|
end
|
61
|
-
country_data.delete(
|
61
|
+
country_data.delete(:validations) if country_data[:validations].empty? && override
|
62
62
|
end
|
63
63
|
|
64
64
|
def load_base_attributes(country_data, territory)
|
65
65
|
territory.attributes.each do |key, value_object|
|
66
66
|
underscored_key = underscore(key).to_sym
|
67
|
-
country_data[underscored_key] = if underscored_key ==
|
67
|
+
country_data[underscored_key] = if underscored_key == :national_prefix_for_parsing
|
68
68
|
value_object.value.delete("\n ")
|
69
69
|
else
|
70
70
|
value_object.value
|
@@ -94,4 +94,3 @@ module TelephoneNumber
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
97
|
-
|
@@ -1,39 +1,28 @@
|
|
1
1
|
module TelephoneNumber
|
2
2
|
class Formatter
|
3
|
-
extend Forwardable
|
4
3
|
|
5
|
-
attr_reader :normalized_number, :
|
4
|
+
attr_reader :normalized_number, :country, :valid, :original_number
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(number_obj, phone_data)
|
6
|
+
def initialize(number_obj)
|
10
7
|
@normalized_number = number_obj.normalized_number
|
11
|
-
@
|
8
|
+
@country = number_obj.country
|
12
9
|
@valid = number_obj.valid?
|
10
|
+
@original_number = number_obj.original_number
|
13
11
|
end
|
14
12
|
|
15
13
|
def national_number(formatted: true)
|
16
|
-
if
|
17
|
-
|
18
|
-
else
|
19
|
-
@national_number ||= build_national_number(formatted: false)
|
20
|
-
end
|
14
|
+
return original_or_default if !valid? || !number_format
|
15
|
+
build_national_number(formatted: formatted)
|
21
16
|
end
|
22
17
|
|
23
18
|
def e164_number(formatted: true)
|
24
|
-
if
|
25
|
-
|
26
|
-
else
|
27
|
-
@e164_number ||= build_e164_number(formatted: false)
|
28
|
-
end
|
19
|
+
return original_or_default if !valid?
|
20
|
+
build_e164_number(formatted: formatted)
|
29
21
|
end
|
30
22
|
|
31
23
|
def international_number(formatted: true)
|
32
|
-
if
|
33
|
-
|
34
|
-
else
|
35
|
-
@international_number ||= build_international_number(formatted: false)
|
36
|
-
end
|
24
|
+
return original_or_default if !valid? || !number_format
|
25
|
+
build_international_number(formatted: formatted)
|
37
26
|
end
|
38
27
|
|
39
28
|
alias_method :valid?, :valid
|
@@ -41,73 +30,47 @@ module TelephoneNumber
|
|
41
30
|
private
|
42
31
|
|
43
32
|
def number_format
|
44
|
-
@number_format ||=
|
33
|
+
@number_format ||= country.detect_format(normalized_number)
|
45
34
|
end
|
46
35
|
|
47
36
|
def build_national_number(formatted: true)
|
48
|
-
|
49
|
-
|
50
|
-
national_prefix_formatting_rule = number_format[PhoneData::NATIONAL_PREFIX_FORMATTING_RULE] \
|
51
|
-
|| country_data[PhoneData::NATIONAL_PREFIX_FORMATTING_RULE]
|
37
|
+
captures = normalized_number.match(number_format.pattern).captures
|
38
|
+
national_prefix_formatting_rule = number_format.national_prefix_formatting_rule || country.national_prefix_formatting_rule
|
52
39
|
|
53
|
-
formatted_string = format(ruby_format_string(number_format
|
54
|
-
captures.delete(
|
40
|
+
formatted_string = format(ruby_format_string(number_format.format), *captures)
|
41
|
+
captures.delete(country.mobile_token)
|
55
42
|
|
56
43
|
if national_prefix_formatting_rule
|
57
44
|
national_prefix_string = national_prefix_formatting_rule.dup
|
58
|
-
national_prefix_string.gsub!(/\$NP/,
|
45
|
+
national_prefix_string.gsub!(/\$NP/, country.national_prefix)
|
59
46
|
national_prefix_string.gsub!(/\$FG/, captures[0])
|
60
47
|
formatted_string.sub!(captures[0], national_prefix_string)
|
61
48
|
end
|
62
49
|
|
63
|
-
formatted ? formatted_string :
|
50
|
+
formatted ? formatted_string : TelephoneNumber.sanitize(formatted_string)
|
64
51
|
end
|
65
52
|
|
66
53
|
def build_e164_number(formatted: true)
|
67
|
-
|
68
|
-
formatted_string
|
69
|
-
formatted ? formatted_string : Parser.sanitize(formatted_string)
|
54
|
+
formatted_string = "+#{country.country_code}#{normalized_number}"
|
55
|
+
formatted ? formatted_string : TelephoneNumber.sanitize(formatted_string)
|
70
56
|
end
|
71
57
|
|
72
58
|
def build_international_number(formatted: true)
|
73
|
-
return
|
74
|
-
captures = normalized_number.match(
|
75
|
-
key = number_format.
|
76
|
-
formatted_string = "+#{
|
77
|
-
formatted ? formatted_string :
|
59
|
+
return original_or_default if !valid? || number_format.nil?
|
60
|
+
captures = normalized_number.match(number_format.pattern).captures
|
61
|
+
key = number_format.intl_format || number_format.format
|
62
|
+
formatted_string = "+#{country.country_code} #{format(ruby_format_string(key), *captures)}"
|
63
|
+
formatted ? formatted_string : TelephoneNumber.sanitize(formatted_string)
|
78
64
|
end
|
79
65
|
|
80
66
|
def ruby_format_string(format_string)
|
81
67
|
format_string.gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
|
82
68
|
end
|
83
69
|
|
84
|
-
def
|
85
|
-
return
|
86
|
-
captures =
|
70
|
+
def original_or_default
|
71
|
+
return original_number unless TelephoneNumber.default_format_string && TelephoneNumber.default_format_pattern
|
72
|
+
captures = original_number.match(TelephoneNumber.default_format_pattern).captures
|
87
73
|
format(ruby_format_string(TelephoneNumber.default_format_string), *captures)
|
88
74
|
end
|
89
|
-
|
90
|
-
def extract_number_format
|
91
|
-
native_country_format = detect_format(country.to_sym)
|
92
|
-
return native_country_format if native_country_format
|
93
|
-
|
94
|
-
# This means we couldn't find an applicable format so we now need to scan through the hierarchy
|
95
|
-
parent_country_code = PhoneData.phone_data.detect do |_country_code, country_data|
|
96
|
-
country_data[PhoneData::COUNTRY_CODE] == PhoneData.phone_data[self.country.to_sym][PhoneData::COUNTRY_CODE] \
|
97
|
-
&& country_data[PhoneData::MAIN_COUNTRY_FOR_CODE] == 'true'
|
98
|
-
end
|
99
|
-
|
100
|
-
detect_format(parent_country_code[0]) if parent_country_code
|
101
|
-
end
|
102
|
-
|
103
|
-
def detect_format(country_code)
|
104
|
-
PhoneData.phone_data[country_code.to_sym][PhoneData::FORMATS].detect do |format|
|
105
|
-
(format[PhoneData::LEADING_DIGITS].nil? \
|
106
|
-
|| normalized_number =~ Regexp.new("^(#{format[PhoneData::LEADING_DIGITS]})")) \
|
107
|
-
&& normalized_number =~ Regexp.new("^(#{format[PhoneData::PATTERN]})$")
|
108
|
-
end
|
109
|
-
end
|
110
75
|
end
|
111
76
|
end
|
112
|
-
|
113
|
-
|
@@ -2,15 +2,16 @@ module TelephoneNumber
|
|
2
2
|
class Number
|
3
3
|
extend Forwardable
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :country, :parser, :formatter, :original_number
|
6
6
|
|
7
7
|
delegate [:valid?, :valid_types, :normalized_number] => :parser
|
8
8
|
delegate [:national_number, :e164_number, :international_number] => :formatter
|
9
9
|
|
10
10
|
def initialize(number, country)
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
11
|
+
@original_number = number
|
12
|
+
@country = Country.find(country)
|
13
|
+
@parser = Parser.new(self)
|
14
|
+
@formatter = Formatter.new(self)
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module TelephoneNumber
|
2
|
+
class NumberFormat
|
3
|
+
|
4
|
+
attr_reader :pattern, :leading_digits, :format, :national_prefix_formatting_rule, :intl_format
|
5
|
+
|
6
|
+
def initialize(data_hash)
|
7
|
+
@pattern = Regexp.new(data_hash[:pattern]) if data_hash[:pattern]
|
8
|
+
@leading_digits = Regexp.new(data_hash[:leading_digits]) if data_hash[:leading_digits]
|
9
|
+
@format = data_hash[:format]
|
10
|
+
@intl_format = data_hash[:intl_format]
|
11
|
+
@national_prefix_formatting_rule = data_hash[:national_prefix_formatting_rule]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,16 +1,11 @@
|
|
1
1
|
module TelephoneNumber
|
2
2
|
class Parser
|
3
|
-
|
4
|
-
extend Forwardable
|
3
|
+
attr_reader :original_number, :normalized_number, :country
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@sanitized_number = self.class.sanitize(original_number)
|
11
|
-
@phone_data = phone_data
|
12
|
-
@original_number = original_number
|
13
|
-
@normalized_number = build_normalized_number
|
5
|
+
def initialize(number_obj)
|
6
|
+
@original_number = number_obj.original_number
|
7
|
+
@country = number_obj.country
|
8
|
+
@normalized_number = build_normalized_number if @country
|
14
9
|
end
|
15
10
|
|
16
11
|
def valid_types
|
@@ -21,59 +16,35 @@ module TelephoneNumber
|
|
21
16
|
keys.empty? ? !valid_types.empty? : !(valid_types & keys.map(&:to_sym)).empty?
|
22
17
|
end
|
23
18
|
|
24
|
-
def self.detect_country(number)
|
25
|
-
sanitized_number = sanitize(number)
|
26
|
-
detected_country = PhoneData.phone_data.detect(->{[]}) do |two_letter, value|
|
27
|
-
sanitized_number =~ Regexp.new("^#{value[:country_code]}") && new(sanitized_number, PhoneData.new(two_letter)).valid?
|
28
|
-
end.first
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.sanitize(input_number)
|
32
|
-
return input_number.to_s.gsub(/\D/, '')
|
33
|
-
end
|
34
|
-
|
35
19
|
private
|
36
20
|
|
37
|
-
# returns an array of valid types for the normalized number
|
38
|
-
# if array is empty, we can assume that the number is invalid
|
39
|
-
def validate
|
40
|
-
return [] unless country_data
|
41
|
-
applicable_keys = country_data[PhoneData::VALIDATIONS].reject { |key, _value| KEYS_TO_SKIP.include?(key) }
|
42
|
-
applicable_keys.map do |phone_type, validations|
|
43
|
-
full = "^(#{validations[PhoneData::VALID_PATTERN]})$"
|
44
|
-
phone_type.to_sym if normalized_number =~ Regexp.new(full)
|
45
|
-
end.compact
|
46
|
-
end
|
47
|
-
|
48
21
|
# normalized_number is basically a "best effort" at national number without
|
49
22
|
# any formatting. This is what we will use to derive formats, validations and
|
50
23
|
# basically anything else that uses google data
|
51
24
|
def build_normalized_number
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
number_with_correct_prefix = parse_prefix
|
56
|
-
|
57
|
-
reg_string = "^(#{country_code})?"
|
58
|
-
reg_string << "(#{country_data[PhoneData::NATIONAL_PREFIX]})?"
|
59
|
-
reg_string << "(#{country_data[PhoneData::VALIDATIONS][PhoneData::GENERAL][PhoneData::VALID_PATTERN]})$"
|
25
|
+
match_result = parse_prefix.match(country.full_general_pattern)
|
26
|
+
match_result ? match_result[:national_num] : original_number
|
27
|
+
end
|
60
28
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
29
|
+
# returns an array of valid types for the normalized number
|
30
|
+
# if array is empty, we can assume that the number is invalid
|
31
|
+
def validate
|
32
|
+
return [] unless country
|
33
|
+
country.validations.select do |validation|
|
34
|
+
normalized_number =~ Regexp.new("^(#{validation.pattern})$")
|
35
|
+
end.map(&:name)
|
65
36
|
end
|
66
37
|
|
67
38
|
def parse_prefix
|
68
|
-
return
|
69
|
-
duped =
|
70
|
-
match_object = duped.match(
|
39
|
+
return original_number unless country.national_prefix_for_parsing
|
40
|
+
duped = original_number.dup
|
41
|
+
match_object = duped.match(country.national_prefix_for_parsing)
|
71
42
|
|
72
43
|
# we need to do the "start_with?" here because we need to make sure it's not finding
|
73
44
|
# something in the middle of the number. However, we can't modify the regex to do this
|
74
45
|
# for us because it will offset the match groups that are referenced in the transform rules
|
75
|
-
return
|
76
|
-
if
|
46
|
+
return original_number unless match_object && duped.start_with?(match_object[0])
|
47
|
+
if country.national_prefix_transform_rule
|
77
48
|
transform_national_prefix(duped, match_object)
|
78
49
|
else
|
79
50
|
duped.sub!(match_object[0], '')
|
@@ -81,7 +52,7 @@ module TelephoneNumber
|
|
81
52
|
end
|
82
53
|
|
83
54
|
def transform_national_prefix(duped, match_object)
|
84
|
-
if
|
55
|
+
if country.mobile_token && match_object.captures.any?
|
85
56
|
format(build_format_string, duped.sub!(match_object[0], match_object[1]))
|
86
57
|
elsif match_object.captures.none?
|
87
58
|
duped.sub!(match_object[0], '')
|
@@ -91,7 +62,7 @@ module TelephoneNumber
|
|
91
62
|
end
|
92
63
|
|
93
64
|
def build_format_string
|
94
|
-
|
65
|
+
country.national_prefix_transform_rule.gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
|
95
66
|
end
|
96
67
|
end
|
97
68
|
end
|
@@ -6,23 +6,31 @@ module TelephoneNumber
|
|
6
6
|
class TestDataGenerator
|
7
7
|
URL = "https://libphonenumber.appspot.com/phonenumberparser?number=%s&country=%s".freeze
|
8
8
|
COUNTRIES = {
|
9
|
+
AE: %w(971529933171 971553006144 971551000291),
|
9
10
|
AR: %w(111512345678 380151234567 299154104587 01112345678),
|
10
11
|
AU: %w(0467703037),
|
12
|
+
BE: %w(32498485960 32477702206 32474095692),
|
13
|
+
BO: %w(59178500348 59178006138 59178006139),
|
11
14
|
BR: %w(011992339376 1123456789 11961234567),
|
12
15
|
BY: %w(80152450911 294911911 152450911),
|
13
16
|
CA: %w(16135550119 16135550171 16135550112 16135550194
|
14
17
|
16135550122 16135550131 15146708700 14169158200),
|
18
|
+
CH: %w(41794173875 41795061129 41795820985),
|
15
19
|
CL: %w(961234567 221234567),
|
16
20
|
CN: %w(15694876068 13910503766 15845989469 05523245954 04717158875 03748086894),
|
17
21
|
CO: %w(3211234567 12345678),
|
18
22
|
CR: %w(22123456 83123456),
|
19
23
|
DE: %w(15222503070),
|
24
|
+
DK: %w(4524453744 4551622172 4542428484),
|
25
|
+
EC: %w(593992441504 593984657155 593984015053),
|
26
|
+
EE: %w(37253629280 37253682997 37254004517),
|
27
|
+
ES: %w(34606217800 34667751353 34646570628),
|
20
28
|
FR: %w(0607114556),
|
21
29
|
GB: %w(448444156790 442079308181 442076139800 442076361000
|
22
30
|
07780991912 442076299400 442072227888),
|
23
31
|
HK: %w(64636251),
|
32
|
+
HU: %w(36709311285 36709311279 36709311206),
|
24
33
|
IE: %w(0863634875),
|
25
|
-
MX: %w(4423593227 14423593227),
|
26
34
|
IN: %w(915622231515 912942433300 912912510101 911126779191
|
27
35
|
912224818000 917462223999 912266653366 912266325757
|
28
36
|
914066298585 911242451234 911166566162 911123890606
|
@@ -30,14 +38,31 @@ module TelephoneNumber
|
|
30
38
|
1126779191 2224818000 7462223999 2266653366
|
31
39
|
2266325757 4066298585 1242451234 1166566162
|
32
40
|
1123890606 1123583754 09176642499),
|
41
|
+
IT: %w(393478258998 393440161350),
|
33
42
|
JP: %w(312345678 9012345678),
|
43
|
+
KR: %w(821036424812 821053812833 821085894820),
|
44
|
+
MX: %w(4423593227 14423593227),
|
45
|
+
NL: %w(31610958780 31610000852 31611427604),
|
46
|
+
NO: %w(4792272668 4797065876 4792466013),
|
47
|
+
NZ: %w(64212715077 6421577017 64212862111),
|
48
|
+
PE: %w(51994156035 51987527881 51972737259),
|
49
|
+
PH: %w(639285588185 639285588262 639285548190),
|
50
|
+
PL: %w(48665666003 48885882321 48885889958),
|
51
|
+
QA: %w(97470482288 97474798678),
|
52
|
+
RO: %w(40724242563 40727798526 40727735377),
|
53
|
+
SA: %w(966503891468 966501543349 966500939012),
|
54
|
+
SE: %w(46708922920 46723985268 46761001966),
|
34
55
|
SG: %w(96924755),
|
56
|
+
TR: %w(905497728782 905497728780 905497728781),
|
57
|
+
TT: %w(18687804765 18687804843 18687804752),
|
58
|
+
TW: %w(886905627933 886905627901 886905627925),
|
35
59
|
US: %w(16502530000 14044879000 15123435283 13032450086 16175751300
|
36
60
|
3175083345 13128404100 12485934000 19497941600 14257395600 13103106000
|
37
61
|
16086699600 12125650000 14123456700 14157360000 12068761800
|
38
|
-
12023461100 3175082333)
|
62
|
+
12023461100 3175082333),
|
63
|
+
VE: %w(584149993108 584248407260 584248271518),
|
64
|
+
ZA: %w(27826187617 27823014578 27828840632)
|
39
65
|
}.freeze
|
40
|
-
|
41
66
|
def self.import!
|
42
67
|
output_hash = {}
|
43
68
|
fetch_data(output_hash)
|
data/lib/telephone_number.rb
CHANGED
@@ -1,48 +1,17 @@
|
|
1
1
|
require 'telephone_number/version'
|
2
2
|
require 'utilities/hash'
|
3
|
-
require '
|
3
|
+
require 'active_model/telephone_number_validator' if defined?(ActiveModel)
|
4
4
|
|
5
5
|
module TelephoneNumber
|
6
|
-
autoload :DataImporter,
|
6
|
+
autoload :DataImporter, 'telephone_number/data_importer'
|
7
7
|
autoload :TestDataGenerator, 'telephone_number/test_data_generator'
|
8
|
-
autoload :Parser,
|
9
|
-
autoload :Number,
|
10
|
-
autoload :Formatter,
|
11
|
-
autoload :
|
12
|
-
autoload :
|
8
|
+
autoload :Parser, 'telephone_number/parser'
|
9
|
+
autoload :Number, 'telephone_number/number'
|
10
|
+
autoload :Formatter, 'telephone_number/formatter'
|
11
|
+
autoload :Country, 'telephone_number/country'
|
12
|
+
autoload :NumberFormat, 'telephone_number/number_format'
|
13
|
+
autoload :NumberValidation, 'telephone_number/number_validation'
|
14
|
+
autoload :ClassMethods, 'telephone_number/class_methods'
|
13
15
|
|
14
16
|
extend ClassMethods
|
15
|
-
|
16
|
-
# allows users to override the default data
|
17
|
-
@override_file = nil
|
18
|
-
|
19
|
-
# allows users to provide a default format pattern
|
20
|
-
@default_format_pattern = nil
|
21
|
-
|
22
|
-
# allows users to provide a default format string
|
23
|
-
@default_format_string = nil
|
24
|
-
|
25
|
-
def self.override_file=(file_name)
|
26
|
-
@override_file = file_name
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.override_file
|
30
|
-
@override_file
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.default_format_string=(format_string)
|
34
|
-
@default_format_string = format_string
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.default_format_string
|
38
|
-
@default_format_string
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.default_format_pattern=(format_string)
|
42
|
-
@default_format_pattern = Regexp.new(format_string)
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.default_format_pattern
|
46
|
-
@default_format_pattern
|
47
|
-
end
|
48
17
|
end
|
data/lib/utilities/hash.rb
CHANGED
data/telephone_number.gemspec
CHANGED
@@ -24,9 +24,9 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency 'rake'
|
25
25
|
spec.add_development_dependency 'minitest'
|
26
26
|
spec.add_development_dependency 'pry'
|
27
|
-
spec.add_development_dependency 'pry-byebug'
|
28
27
|
spec.add_development_dependency 'nokogiri'
|
29
28
|
spec.add_development_dependency 'httparty'
|
29
|
+
spec.add_development_dependency 'activemodel', '>= 4.0'
|
30
30
|
spec.add_development_dependency 'minitest-focus'
|
31
31
|
spec.add_development_dependency 'coveralls'
|
32
32
|
end
|