telephone_number 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +2 -1
- data/{.ruby.yml → .rubocop.default.yml} +19 -1
- data/.rubocop.yml +4 -0
- data/.travis.yml +5 -3
- data/{LICENSE.txt → LICENSE} +1 -1
- data/README.md +24 -15
- data/Rakefile +6 -0
- data/data/telephone_number_data_file.dat +0 -0
- data/data/telephone_number_data_file.xml +187 -202
- data/lib/telephone_number/class_methods.rb +4 -0
- data/lib/telephone_number/data_importer.rb +21 -6
- data/lib/telephone_number/formatter.rb +60 -0
- data/lib/telephone_number/number.rb +37 -5
- data/lib/telephone_number/parser.rb +51 -22
- data/lib/telephone_number/phone_data.rb +21 -14
- data/lib/telephone_number/test_data_generator.rb +91 -0
- data/lib/telephone_number/version.rb +1 -1
- data/lib/telephone_number.rb +2 -0
- data/telephone_number.gemspec +2 -0
- metadata +35 -5
- data/telephone_number_data_file.xml +0 -27105
@@ -28,19 +28,29 @@ module TelephoneNumber
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def load_formats(country_data, territory)
|
31
|
-
country_data[
|
31
|
+
country_data[PhoneData::FORMATS] = territory.css("availableFormats numberFormat").map do |format|
|
32
32
|
format_hash = {}.tap do |fhash|
|
33
|
-
format.attributes.values.each
|
34
|
-
|
33
|
+
format.attributes.values.each do |attr|
|
34
|
+
key = underscore(attr.name).to_sym
|
35
|
+
fhash[key] = if key == PhoneData::NATIONAL_PREFIX_FORMATTING_RULE
|
36
|
+
attr.value
|
37
|
+
else
|
38
|
+
attr.value.delete("\n ")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
format.elements.each do |child|
|
42
|
+
key = underscore(child.name).to_sym
|
43
|
+
fhash[key] = [PhoneData::FORMAT, PhoneData::INTL_FORMAT].include?(key) ? child.text : child.text.delete("\n ")
|
44
|
+
end
|
35
45
|
end
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
39
49
|
def load_validations(country_data, territory)
|
40
|
-
country_data[
|
50
|
+
country_data[PhoneData::VALIDATIONS] = {}
|
41
51
|
territory.elements.each do |element|
|
42
52
|
next if element.name == "references" || element.name == "availableFormats"
|
43
|
-
country_data[
|
53
|
+
country_data[PhoneData::VALIDATIONS][underscore(element.name).to_sym] = {}.tap do |validation_hash|
|
44
54
|
element.elements.each{|child| validation_hash[underscore(child.name).to_sym] = child.text.delete("\n ")}
|
45
55
|
end
|
46
56
|
end
|
@@ -48,7 +58,12 @@ module TelephoneNumber
|
|
48
58
|
|
49
59
|
def load_base_attributes(country_data, territory)
|
50
60
|
territory.attributes.each do |key, value_object|
|
51
|
-
|
61
|
+
underscored_key = underscore(key).to_sym
|
62
|
+
country_data[underscored_key] = if underscored_key == PhoneData::NATIONAL_PREFIX_FOR_PARSING
|
63
|
+
value_object.value.delete("\n ")
|
64
|
+
else
|
65
|
+
value_object.value
|
66
|
+
end
|
52
67
|
end
|
53
68
|
end
|
54
69
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module TelephoneNumber
|
2
|
+
module Formatter
|
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] \
|
7
|
+
|| country_data[PhoneData::NATIONAL_PREFIX_FORMATTING_RULE]
|
8
|
+
|
9
|
+
format_string = format[PhoneData::FORMAT].gsub(/(\$\d)/) { |cap| "%#{cap.reverse}s" }
|
10
|
+
formatted_string = sprintf(format_string, *captures)
|
11
|
+
captures.delete(PhoneData::MOBILE_TOKEN_COUNTRIES[country])
|
12
|
+
|
13
|
+
if national_prefix_formatting_rule
|
14
|
+
national_prefix_string = national_prefix_formatting_rule.dup
|
15
|
+
national_prefix_string.gsub!(/\$NP/, country_data[PhoneData::NATIONAL_PREFIX])
|
16
|
+
national_prefix_string.gsub!(/\$FG/, captures[0])
|
17
|
+
formatted_string.sub!(captures[0], national_prefix_string)
|
18
|
+
end
|
19
|
+
|
20
|
+
formatted ? formatted_string : sanitize(formatted_string)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_e164_number(formatted: true)
|
24
|
+
formatted_string = "+#{country_data[PhoneData::COUNTRY_CODE]}#{normalized_number}"
|
25
|
+
formatted ? formatted_string : sanitize(formatted_string)
|
26
|
+
end
|
27
|
+
|
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)}"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def extract_format
|
39
|
+
native_country_format = detect_format(country.to_sym)
|
40
|
+
return native_country_format if native_country_format
|
41
|
+
|
42
|
+
# 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|
|
44
|
+
country_data[PhoneData::COUNTRY_CODE] == PhoneData.phone_data[self.country.to_sym][PhoneData::COUNTRY_CODE] \
|
45
|
+
&& country_data[PhoneData::MAIN_COUNTRY_FOR_CODE] == 'true'
|
46
|
+
end
|
47
|
+
detect_format(parent_country_code[0])
|
48
|
+
end
|
49
|
+
|
50
|
+
def detect_format(country_code)
|
51
|
+
PhoneData.phone_data[country_code.to_sym][PhoneData::FORMATS].detect do |format|
|
52
|
+
(format[PhoneData::LEADING_DIGITS].nil? \
|
53
|
+
|| normalized_number =~ Regexp.new("^(#{format[PhoneData::LEADING_DIGITS]})")) \
|
54
|
+
&& normalized_number =~ Regexp.new("^(#{format[PhoneData::PATTERN]})$")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
@@ -1,27 +1,59 @@
|
|
1
1
|
module TelephoneNumber
|
2
2
|
class Number
|
3
3
|
include TelephoneNumber::Parser
|
4
|
+
include TelephoneNumber::Formatter
|
4
5
|
|
5
|
-
attr_reader :original_number, :
|
6
|
+
attr_reader :original_number, :normalized_number, :country, :country_data
|
6
7
|
|
7
8
|
def initialize(number, country)
|
8
9
|
return unless number && country
|
9
10
|
|
10
|
-
@original_number = sanitize(number)
|
11
|
+
@original_number = sanitize(number).freeze
|
11
12
|
@country = country.upcase.to_sym
|
12
|
-
@
|
13
|
+
@country_data = PhoneData.phone_data[@country]
|
14
|
+
|
15
|
+
# normalized_number is basically a "best effort" at national number without
|
16
|
+
# any formatting. This is what we will use to derive formats, validations and
|
17
|
+
# basically anything else that uses google data
|
18
|
+
@normalized_number = build_normalized_number
|
13
19
|
end
|
14
20
|
|
15
21
|
def valid_types
|
16
|
-
@valid_types ||= validate
|
22
|
+
@valid_types ||= validate
|
17
23
|
end
|
18
24
|
|
19
25
|
def valid?(keys = [])
|
20
26
|
keys.empty? ? !valid_types.empty? : !(valid_types & keys.map(&:to_sym)).empty?
|
21
27
|
end
|
22
28
|
|
29
|
+
def national_number(formatted: true)
|
30
|
+
if formatted
|
31
|
+
@formatted_national_number ||= build_national_number
|
32
|
+
else
|
33
|
+
@unformatted_national_number ||= build_national_number(formatted: false)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def e164_number(formatted: true)
|
38
|
+
if formatted
|
39
|
+
@formatted_e164_number ||= build_e164_number
|
40
|
+
else
|
41
|
+
@e164_number ||= build_e164_number(formatted: false)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def international_number(formatted: true)
|
46
|
+
if formatted
|
47
|
+
@formatted_international_number ||= build_international_number
|
48
|
+
else
|
49
|
+
@international_number ||= build_international_number(formatted: false)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
23
55
|
def format
|
24
|
-
@format ||= extract_format
|
56
|
+
@format ||= extract_format
|
25
57
|
end
|
26
58
|
end
|
27
59
|
end
|
@@ -1,39 +1,68 @@
|
|
1
1
|
module TelephoneNumber
|
2
2
|
module Parser
|
3
|
-
KEYS_TO_SKIP = [
|
4
|
-
TelephoneNumber::PhoneData::AREA_CODE_OPTIONAL]
|
3
|
+
KEYS_TO_SKIP = [PhoneData::GENERAL, PhoneData::AREA_CODE_OPTIONAL]
|
5
4
|
|
6
5
|
def sanitize(input_number)
|
7
6
|
return input_number.gsub(/[^0-9]/, "")
|
8
7
|
end
|
9
8
|
|
10
|
-
|
11
|
-
|
9
|
+
# returns an array of valid types for the normalized number
|
10
|
+
# if array is empty, we can assume that the number is invalid
|
11
|
+
def validate
|
12
|
+
return [] unless country_data
|
13
|
+
applicable_keys = country_data[PhoneData::VALIDATIONS].reject{ |key, _value| KEYS_TO_SKIP.include?(key) }
|
14
|
+
applicable_keys.map do |phone_type, validations|
|
15
|
+
full = "^(#{validations[PhoneData::VALID_PATTERN]})$"
|
16
|
+
phone_type.to_sym if normalized_number =~ Regexp.new(full)
|
17
|
+
end.compact
|
18
|
+
end
|
12
19
|
|
13
|
-
|
14
|
-
country_code = country_data[TelephoneNumber::PhoneData::COUNTRY_CODE]
|
20
|
+
private
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
def build_normalized_number
|
23
|
+
return original_number unless country_data
|
24
|
+
country_code = country_data[PhoneData::COUNTRY_CODE]
|
25
|
+
|
26
|
+
number_with_correct_prefix = parse_prefix
|
21
27
|
|
22
|
-
|
28
|
+
reg_string = "^(#{country_code})?"
|
29
|
+
reg_string << "(#{country_data[PhoneData::NATIONAL_PREFIX]})?"
|
30
|
+
reg_string << "(#{country_data[PhoneData::VALIDATIONS][PhoneData::GENERAL][PhoneData::VALID_PATTERN]})$"
|
23
31
|
|
32
|
+
match_result = number_with_correct_prefix.match(Regexp.new(reg_string))
|
33
|
+
return original_number unless match_result
|
24
34
|
prefix_results = [match_result[1], match_result[2]]
|
25
|
-
|
26
|
-
[without_prefix, "#{country_code}#{without_prefix}"]
|
35
|
+
number_with_correct_prefix.sub(prefix_results.join, '')
|
27
36
|
end
|
28
37
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
38
|
+
def parse_prefix
|
39
|
+
return original_number unless country_data[:national_prefix_for_parsing]
|
40
|
+
duped = original_number.dup
|
41
|
+
match_object = duped.match(Regexp.new(country_data[:national_prefix_for_parsing]))
|
42
|
+
|
43
|
+
# we need to do the "start_with?" here because we need to make sure it's not finding
|
44
|
+
# something in the middle of the number. However, we can't modify the regex to do this
|
45
|
+
# for us because it will offset the match groups that are referenced in the transform rules
|
46
|
+
return original_number unless match_object && duped.start_with?(match_object[0])
|
47
|
+
if country_data[:national_prefix_transform_rule]
|
48
|
+
transform_national_prefix(duped, match_object)
|
49
|
+
else
|
50
|
+
duped.sub!(match_object[0], '')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def transform_national_prefix(duped, match_object)
|
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]))
|
57
|
+
elsif match_object.captures.none?
|
58
|
+
duped.sub!(match_object[0], '')
|
59
|
+
else
|
60
|
+
sprintf(build_format_string, *match_object.captures)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_format_string
|
65
|
+
country_data[:national_prefix_transform_rule].gsub(/(\$\d)/) {|cap| "%#{cap.reverse}s"}
|
37
66
|
end
|
38
67
|
end
|
39
68
|
end
|
@@ -1,25 +1,32 @@
|
|
1
1
|
module TelephoneNumber
|
2
2
|
module PhoneData
|
3
|
-
|
3
|
+
AREA_CODE_OPTIONAL = :area_code_optional.freeze
|
4
|
+
COUNTRY_CODE = :country_code.freeze
|
5
|
+
FIXED_LINE = :fixed_line.freeze
|
4
6
|
FORMATS = :formats.freeze
|
7
|
+
FORMAT = :format.freeze
|
5
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
|
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
|
19
|
+
PATTERN = :pattern
|
20
|
+
PERSONAL_NUMBER = :personal_number.freeze
|
21
|
+
POSSIBLE_PATTERN = :possible_number_pattern.freeze
|
6
22
|
PREMIUM_RATE = :premium_rate.freeze
|
7
|
-
TOLL_FREE = :toll_free.freeze
|
8
23
|
SHARED_COST = :shared_cost.freeze
|
9
|
-
|
10
|
-
PERSONAL_NUMBER = :personal_number.freeze
|
24
|
+
TOLL_FREE = :toll_free.freeze
|
11
25
|
UAN = :uan.freeze
|
12
|
-
|
13
|
-
FIXED_LINE = :fixed_line.freeze
|
14
|
-
MOBILE = :mobile.freeze
|
15
|
-
NO_INTERNATIONAL_DIALING = :no_international_dialling.freeze
|
16
|
-
AREA_CODE_OPTIONAL = :area_code_optional.freeze
|
26
|
+
VALIDATIONS = :validations.freeze
|
17
27
|
VALID_PATTERN = :national_number_pattern.freeze
|
18
|
-
|
19
|
-
|
20
|
-
COUNTRY_CODE = :country_code.freeze
|
21
|
-
LEADING_DIGITS = :leading_digits.freeze
|
22
|
-
INTERNATIONAL_PREFIX = :international_prefix.freeze
|
28
|
+
VOICEMAIL = :voicemail.freeze
|
29
|
+
VOIP = :voip.freeze
|
23
30
|
|
24
31
|
def self.phone_data
|
25
32
|
@@phone_data ||= load_data
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module TelephoneNumber
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'httparty'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
class TestDataGenerator
|
7
|
+
URL = "https://libphonenumber.appspot.com/phonenumberparser?number=%s&country=%s".freeze
|
8
|
+
COUNTRIES = {
|
9
|
+
AR: %w(111512345678 380151234567 299154104587 01112345678),
|
10
|
+
AU: %w(0467703037),
|
11
|
+
BR: %w(011992339376 1123456789 11961234567),
|
12
|
+
BY: %w(80152450911 294911911 152450911),
|
13
|
+
CA: %w(16135550119 16135550171 16135550112 16135550194
|
14
|
+
16135550122 16135550131 15146708700 14169158200),
|
15
|
+
CL: %w(961234567 221234567),
|
16
|
+
CN: %w(15694876068 13910503766 15845989469 05523245954 04717158875 03748086894),
|
17
|
+
CO: %w(3211234567 12345678),
|
18
|
+
CR: %w(22123456 83123456),
|
19
|
+
DE: %w(15222503070),
|
20
|
+
FR: %w(0607114556),
|
21
|
+
GB: %w(448444156790 442079308181 442076139800 442076361000
|
22
|
+
07780991912 442076299400 442072227888),
|
23
|
+
HK: %w(64636251),
|
24
|
+
IE: %w(0863634875),
|
25
|
+
MX: %w(4423593227 14423593227),
|
26
|
+
IN: %w(915622231515 912942433300 912912510101 911126779191
|
27
|
+
912224818000 917462223999 912266653366 912266325757
|
28
|
+
914066298585 911242451234 911166566162 911123890606
|
29
|
+
911123583754 5622231515 2942433300 2912510101
|
30
|
+
1126779191 2224818000 7462223999 2266653366
|
31
|
+
2266325757 4066298585 1242451234 1166566162
|
32
|
+
1123890606 1123583754 09176642499),
|
33
|
+
JP: %w(312345678 9012345678),
|
34
|
+
SG: %w(96924755),
|
35
|
+
US: %w(16502530000 14044879000 15123435283 13032450086 16175751300
|
36
|
+
3175083345 13128404100 12485934000 19497941600 14257395600 13103106000
|
37
|
+
16086699600 12125650000 14123456700 14157360000 12068761800
|
38
|
+
12023461100 3175082333)
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
def self.import!
|
42
|
+
output_hash = {}
|
43
|
+
fetch_data(output_hash)
|
44
|
+
write_file(output_hash)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.fetch_data(output_hash)
|
49
|
+
COUNTRIES.each do |key, value|
|
50
|
+
output_hash[key] = {}
|
51
|
+
|
52
|
+
value.each_with_index do |num, counter|
|
53
|
+
page = HTTParty.get(sprintf(URL, num, key.to_s))
|
54
|
+
parsed_page = Nokogiri::HTML.parse(page)
|
55
|
+
body = parsed_page.elements.first.elements.css('body').first
|
56
|
+
parsed_data = parse_remote_data(counter, body.elements.css('table')[2])
|
57
|
+
output_hash[key].merge!(parsed_data)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
return output_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.parse_remote_data(counter, table)
|
64
|
+
output = { counter.to_s => {} }
|
65
|
+
table.elements.each do |row|
|
66
|
+
next if row.elements.one?
|
67
|
+
key = case row.elements.css('th').text
|
68
|
+
when 'E164 format'
|
69
|
+
:e164_formatted
|
70
|
+
when 'National format'
|
71
|
+
:national_formatted
|
72
|
+
when 'International format'
|
73
|
+
:international_formatted
|
74
|
+
end
|
75
|
+
|
76
|
+
output[counter.to_s][key] = row.elements.css('td').text if key
|
77
|
+
end
|
78
|
+
return output
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.write_file(data)
|
82
|
+
File.open('test/valid_numbers.yml', 'w') do |file|
|
83
|
+
file.write "# This file is generated automatically by TestDataGenerator. \n" \
|
84
|
+
"# Any changes made to this file will be overridden next time test data is generated. \n" \
|
85
|
+
"# Please edit TestDataGenerator if you need to add test cases. \n"
|
86
|
+
|
87
|
+
file.write data.to_yaml
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/telephone_number.rb
CHANGED
@@ -2,8 +2,10 @@ require "telephone_number/version"
|
|
2
2
|
|
3
3
|
module TelephoneNumber
|
4
4
|
autoload :DataImporter, 'telephone_number/data_importer'
|
5
|
+
autoload :TestDataGenerator, 'telephone_number/test_data_generator'
|
5
6
|
autoload :Parser, 'telephone_number/parser'
|
6
7
|
autoload :Number, 'telephone_number/number'
|
8
|
+
autoload :Formatter, 'telephone_number/formatter'
|
7
9
|
autoload :PhoneData, 'telephone_number/phone_data'
|
8
10
|
autoload :ClassMethods, 'telephone_number/class_methods'
|
9
11
|
|
data/telephone_number.gemspec
CHANGED
@@ -26,5 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency "pry"
|
27
27
|
spec.add_development_dependency "pry-byebug"
|
28
28
|
spec.add_development_dependency "nokogiri"
|
29
|
+
spec.add_development_dependency "httparty"
|
29
30
|
spec.add_development_dependency "minitest-focus"
|
31
|
+
spec.add_development_dependency 'coveralls'
|
30
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.2.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-01
|
11
|
+
date: 2017-02-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: httparty
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: minitest-focus
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,20 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: coveralls
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
111
139
|
description:
|
112
140
|
email:
|
113
141
|
- adam.fernung@mobiwm.com
|
@@ -118,12 +146,13 @@ extra_rdoc_files: []
|
|
118
146
|
files:
|
119
147
|
- ".gitignore"
|
120
148
|
- ".hound.yml"
|
149
|
+
- ".rubocop.default.yml"
|
150
|
+
- ".rubocop.yml"
|
121
151
|
- ".ruby-version"
|
122
|
-
- ".ruby.yml"
|
123
152
|
- ".travis.yml"
|
124
153
|
- CODE_OF_CONDUCT.md
|
125
154
|
- Gemfile
|
126
|
-
- LICENSE
|
155
|
+
- LICENSE
|
127
156
|
- README.md
|
128
157
|
- Rakefile
|
129
158
|
- bin/console
|
@@ -133,12 +162,13 @@ files:
|
|
133
162
|
- lib/telephone_number.rb
|
134
163
|
- lib/telephone_number/class_methods.rb
|
135
164
|
- lib/telephone_number/data_importer.rb
|
165
|
+
- lib/telephone_number/formatter.rb
|
136
166
|
- lib/telephone_number/number.rb
|
137
167
|
- lib/telephone_number/parser.rb
|
138
168
|
- lib/telephone_number/phone_data.rb
|
169
|
+
- lib/telephone_number/test_data_generator.rb
|
139
170
|
- lib/telephone_number/version.rb
|
140
171
|
- telephone_number.gemspec
|
141
|
-
- telephone_number_data_file.xml
|
142
172
|
homepage: https://github.com/mobi/telephone_number
|
143
173
|
licenses:
|
144
174
|
- MIT
|