countries-phone_numbers 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/countries-phone_numbers.gemspec +3 -0
- data/lib/countries/iso3166.rb +10 -35
- data/lib/countries/phone_numbers/country_detector.rb +0 -12
- data/lib/countries/phone_numbers/detector_factory.rb +49 -0
- data/lib/countries/phone_numbers/{country_detectors.yaml → detectors.yaml} +0 -0
- data/lib/countries/phone_numbers/version.rb +1 -1
- data/lib/countries/phone_numbers.rb +2 -0
- data/spec/countries/phone_numbers/detector_factory_spec.rb +111 -0
- data/spec/spec_helper.rb +5 -0
- metadata +34 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86db77726a2eb98b11c2aef026b1d121d3dcd184
|
|
4
|
+
data.tar.gz: b0083df537fe9839eb25f25a1a19148d4b581e2d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: db79a2bdc029e69156295bc0790c4034e4c213dc72d60ed70bff13ff3a972541dfbf7b94f6effc150f3d946774143ca3202fdcb57c908dbdc058d0917f41e8d9
|
|
7
|
+
data.tar.gz: 2058fb544e19f9da9b3f9734f6112ec8043fa78e51513c9db3b6a524873ef705aa7f1ad7b842100498b21998f45c43c780bb54177f25dbb92196e3732848e837
|
|
@@ -24,4 +24,7 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
|
25
25
|
spec.add_development_dependency "rake"
|
|
26
26
|
spec.add_development_dependency "rspec"
|
|
27
|
+
spec.add_development_dependency "json"
|
|
28
|
+
spec.add_development_dependency "simplecov"
|
|
29
|
+
|
|
27
30
|
end
|
data/lib/countries/iso3166.rb
CHANGED
|
@@ -8,7 +8,7 @@ class ISO3166::Country
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def self.tokenize_phone_number( number )
|
|
11
|
-
Phony.split(
|
|
11
|
+
Phony.split( normalize_phone_number( number ) )
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
##
|
|
@@ -23,15 +23,16 @@ class ISO3166::Country
|
|
|
23
23
|
# Generally we try to eliminate duplicates by using country code specific detectors.
|
|
24
24
|
def self.find_all_by_phone_number( number )
|
|
25
25
|
normalised_number = tokenize_phone_number( number )
|
|
26
|
+
country_code = normalised_number.first
|
|
26
27
|
|
|
27
28
|
# Is this a detector country?
|
|
28
|
-
detector =
|
|
29
|
+
detector = phone_number_detector_factory.detector_for( country_code )
|
|
29
30
|
if detector
|
|
30
31
|
return detector.find_all_by_phone_number( normalised_number )
|
|
31
32
|
|
|
32
33
|
# Otherwise ask the general code base for the number
|
|
33
34
|
else
|
|
34
|
-
return
|
|
35
|
+
return find_all_by_country_code( country_code )
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
rescue
|
|
@@ -50,33 +51,22 @@ class ISO3166::Country
|
|
|
50
51
|
# Generally we try to eliminate duplicates by using country code specific detectors.
|
|
51
52
|
def self.find_all_countries_by_phone_number( number )
|
|
52
53
|
normalised_number = tokenize_phone_number( number )
|
|
54
|
+
country_code = normalised_number.first
|
|
53
55
|
|
|
54
56
|
# Is this a detector country?
|
|
55
|
-
detector =
|
|
57
|
+
detector = phone_number_detector_factory.detector_for( country_code )
|
|
56
58
|
if detector
|
|
57
59
|
return detector.find_all_countries_by_phone_number( normalised_number )
|
|
58
60
|
|
|
59
61
|
# Otherwise ask the general code base for the number
|
|
60
62
|
else
|
|
61
|
-
return
|
|
63
|
+
return find_all_countries_by_country_code( country_code )
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
rescue
|
|
65
67
|
return nil
|
|
66
68
|
end
|
|
67
69
|
|
|
68
|
-
##
|
|
69
|
-
# Get the requested phone number detector based on the phone number's prefix.
|
|
70
|
-
def self.phone_number_detector_for( prefix )
|
|
71
|
-
prefix = prefix.to_s
|
|
72
|
-
detector = phone_number_detectors[ prefix ]
|
|
73
|
-
if detector.is_a? Hash
|
|
74
|
-
detector = Countries::PhoneNumbers::CountryDetector.build( detector )
|
|
75
|
-
phone_number_detectors[ prefix ] = detector
|
|
76
|
-
end
|
|
77
|
-
detector
|
|
78
|
-
end
|
|
79
|
-
|
|
80
70
|
##
|
|
81
71
|
# Find all countries with shared country codes.
|
|
82
72
|
def self.shared_country_codes
|
|
@@ -89,28 +79,13 @@ class ISO3166::Country
|
|
|
89
79
|
##
|
|
90
80
|
# Find all countries with shared country codes and do not have a dedicated detector.
|
|
91
81
|
def self.unresolved_country_codes
|
|
92
|
-
self.shared_country_codes.reject{ |key,value| self.
|
|
82
|
+
self.shared_country_codes.reject{ |key,value| self.phone_number_detector_factory.detector_for? key or key == '' }
|
|
93
83
|
end
|
|
94
84
|
|
|
95
85
|
protected
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def self.phone_number_detectors
|
|
100
|
-
@@phone_number_detectors ||= load_phone_number_detector_config
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
##
|
|
104
|
-
# Load phone number detector configuration.
|
|
105
|
-
def self.load_phone_number_detector_config
|
|
106
|
-
filename = File.join( 'lib', 'countries', 'phone_numbers', 'country_detectors.yaml' )
|
|
107
|
-
config = {}
|
|
108
|
-
File.open( filename ) do |file|
|
|
109
|
-
YAML.load_documents( file ) do |doc|
|
|
110
|
-
config[doc['applies_to'].to_s] = doc
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
config
|
|
87
|
+
def self.phone_number_detector_factory
|
|
88
|
+
@@phone_number_detector_factory ||= Countries::PhoneNumbers::DetectorFactory.new
|
|
114
89
|
end
|
|
115
90
|
|
|
116
91
|
end
|
|
@@ -2,18 +2,6 @@ class Countries::PhoneNumbers::CountryDetector
|
|
|
2
2
|
|
|
3
3
|
attr_accessor :country_codes, :applies_to, :default
|
|
4
4
|
|
|
5
|
-
def self.build config
|
|
6
|
-
# Build a new config tool based on the given strategy
|
|
7
|
-
return case
|
|
8
|
-
when config.include?('start_with')
|
|
9
|
-
Countries::PhoneNumbers::StartWithCountryDetector.new config
|
|
10
|
-
when config.include?('one_of')
|
|
11
|
-
Countries::PhoneNumbers::OneOfCountryDetector.new config
|
|
12
|
-
else
|
|
13
|
-
Countries::PhoneNumbers::CountryDetector.new config
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
5
|
def initialize config
|
|
18
6
|
self.applies_to = config['applies_to'].to_s
|
|
19
7
|
self.default = config['default'].to_s
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class Countries::PhoneNumbers::DetectorFactory
|
|
2
|
+
|
|
3
|
+
attr_accessor :config, :detectors
|
|
4
|
+
|
|
5
|
+
def initialize( config=Countries::PhoneNumbers::DATA_FILE )
|
|
6
|
+
@config = config.is_a?(Hash) ? config : {}
|
|
7
|
+
@detectors = {}
|
|
8
|
+
load_config_file( config ) if config.is_a?(String)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def load_config_file( filename )
|
|
12
|
+
File.open( filename ) do |file|
|
|
13
|
+
YAML.load_documents( file ) { |doc| add_config( doc ) }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_config( cc )
|
|
18
|
+
key = cc['applies_to'].to_s
|
|
19
|
+
config[key] = cc
|
|
20
|
+
detectors.delete(key)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def detector_for?( prefix )
|
|
24
|
+
config.include? prefix.to_s
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def detector_for( prefix )
|
|
28
|
+
prefix = prefix.to_s
|
|
29
|
+
if detector_for? prefix
|
|
30
|
+
detectors[prefix] = build_detector( config[prefix] ) unless detectors.include? prefix
|
|
31
|
+
end
|
|
32
|
+
return detectors[prefix]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
protected
|
|
36
|
+
|
|
37
|
+
def build_detector( config )
|
|
38
|
+
# Build a new config tool based on the given strategy
|
|
39
|
+
return case
|
|
40
|
+
when config.include?('start_with')
|
|
41
|
+
Countries::PhoneNumbers::StartWithCountryDetector.new config
|
|
42
|
+
when config.include?('one_of')
|
|
43
|
+
Countries::PhoneNumbers::OneOfCountryDetector.new config
|
|
44
|
+
else
|
|
45
|
+
Countries::PhoneNumbers::CountryDetector.new config
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
File without changes
|
|
@@ -5,6 +5,7 @@ require 'countries'
|
|
|
5
5
|
require 'phony'
|
|
6
6
|
|
|
7
7
|
# Country::PhoneNumber
|
|
8
|
+
require 'countries/phone_numbers/detector_factory'
|
|
8
9
|
require 'countries/phone_numbers/country_detector'
|
|
9
10
|
require 'countries/phone_numbers/one_of_country_detector'
|
|
10
11
|
require 'countries/phone_numbers/start_with_country_detector'
|
|
@@ -14,5 +15,6 @@ require 'countries/iso3166'
|
|
|
14
15
|
|
|
15
16
|
module Countries
|
|
16
17
|
module PhoneNumbers
|
|
18
|
+
DATA_FILE = File.join( 'lib', 'countries', 'phone_numbers', 'detectors.yaml' )
|
|
17
19
|
end
|
|
18
20
|
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'countries/phone_numbers'
|
|
3
|
+
|
|
4
|
+
describe Countries::PhoneNumbers::DetectorFactory do
|
|
5
|
+
subject { Countries::PhoneNumbers::DetectorFactory.new({}) }
|
|
6
|
+
let(:applies_to) { '1' }
|
|
7
|
+
let(:one_of_prefix) { '222' }
|
|
8
|
+
let(:start_with_prefix) { '333' }
|
|
9
|
+
let(:default_country) { 'US' }
|
|
10
|
+
let(:alternate_country) { 'GB' }
|
|
11
|
+
|
|
12
|
+
let(:default_config) { { 'applies_to' => applies_to, 'default' => default_country } }
|
|
13
|
+
let(:one_of_config) { { 'applies_to' => applies_to, 'default' => default_country, 'one_of' => { alternate_country => [ one_of_prefix ] } } }
|
|
14
|
+
let(:start_with_config) { { 'applies_to' => applies_to, 'default' => default_country, 'start_with' => { alternate_country => [ start_with_prefix ] } } }
|
|
15
|
+
|
|
16
|
+
let(:default_detector) { Countries::PhoneNumbers::CountryDetector.new(default_config) }
|
|
17
|
+
|
|
18
|
+
describe '.new' do
|
|
19
|
+
|
|
20
|
+
context 'using a config file' do
|
|
21
|
+
subject { Countries::PhoneNumbers::DetectorFactory.new(Countries::PhoneNumbers::DATA_FILE) }
|
|
22
|
+
it 'loads the config file' do
|
|
23
|
+
expect( subject.config ).not_to be_empty
|
|
24
|
+
end
|
|
25
|
+
it 'starts with no detectors' do
|
|
26
|
+
expect( subject.detectors ).to be_empty
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'using a config hash' do
|
|
31
|
+
let(:config) { { applies_to => default_config } }
|
|
32
|
+
subject { Countries::PhoneNumbers::DetectorFactory.new(config) }
|
|
33
|
+
it 'saves the config' do
|
|
34
|
+
expect( subject.config ).to eq(config)
|
|
35
|
+
end
|
|
36
|
+
it 'starts with no detectors' do
|
|
37
|
+
expect( subject.detectors ).to be_empty
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#load_config_file' do
|
|
44
|
+
it 'loads a config file' do
|
|
45
|
+
expect{ subject.load_config_file( Countries::PhoneNumbers::DATA_FILE ) }.to change{subject.config.size}.from(0)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe '#add_config' do
|
|
50
|
+
before { subject.detectors[applies_to] = default_detector }
|
|
51
|
+
|
|
52
|
+
it 'adds a new config' do
|
|
53
|
+
expect{ subject.add_config(default_config) }.to change{subject.config.size}.by(1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'stores config by key' do
|
|
57
|
+
subject.add_config(default_config)
|
|
58
|
+
expect( subject.config ).to include(applies_to)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'saves config by key' do
|
|
62
|
+
subject.add_config(default_config)
|
|
63
|
+
expect( subject.config[applies_to] ).to be default_config
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'deletes the existing detector' do
|
|
67
|
+
expect{ subject.add_config(default_config) }.to change{ subject.detectors[applies_to] }.to(nil)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe '#detector_for?' do
|
|
72
|
+
it 'detects config' do
|
|
73
|
+
expect{ subject.add_config(default_config) }.to change{ subject.detector_for? applies_to }.from(false).to(true)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe '#detector_for' do
|
|
78
|
+
before do
|
|
79
|
+
subject.add_config( default_config )
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'reuses an existing detector' do
|
|
83
|
+
subject.detectors[applies_to] = default_detector
|
|
84
|
+
expect(subject.detector_for(applies_to)).to eq(default_detector)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'creates a new detector on demand' do
|
|
88
|
+
subject.add_config( default_config )
|
|
89
|
+
expect{ subject.detector_for(applies_to) }.to change{ subject.detectors[applies_to] }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'returns nil when no detector configured' do
|
|
93
|
+
expect( subject.detector_for('2') ).to be_nil
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe '#build_detector' do
|
|
98
|
+
it 'returns a generic detector' do
|
|
99
|
+
expect( subject.send(:build_detector, default_config) ).to be_a(Countries::PhoneNumbers::CountryDetector)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it 'returns a one-of detector' do
|
|
103
|
+
expect( subject.send(:build_detector, one_of_config) ).to be_a(Countries::PhoneNumbers::OneOfCountryDetector)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'returns a start-with detector' do
|
|
107
|
+
expect( subject.send(:build_detector, start_with_config) ).to be_a(Countries::PhoneNumbers::StartWithCountryDetector)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: countries-phone_numbers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ian Lloyd
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-12-
|
|
11
|
+
date: 2013-12-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: countries
|
|
@@ -80,6 +80,34 @@ dependencies:
|
|
|
80
80
|
- - '>='
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: json
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - '>='
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - '>='
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: simplecov
|
|
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'
|
|
83
111
|
description: Find countries by phone numbers
|
|
84
112
|
email:
|
|
85
113
|
- ian.w.lloyd@me.com
|
|
@@ -97,11 +125,13 @@ files:
|
|
|
97
125
|
- lib/countries/iso3166.rb
|
|
98
126
|
- lib/countries/phone_numbers.rb
|
|
99
127
|
- lib/countries/phone_numbers/country_detector.rb
|
|
100
|
-
- lib/countries/phone_numbers/
|
|
128
|
+
- lib/countries/phone_numbers/detector_factory.rb
|
|
129
|
+
- lib/countries/phone_numbers/detectors.yaml
|
|
101
130
|
- lib/countries/phone_numbers/one_of_country_detector.rb
|
|
102
131
|
- lib/countries/phone_numbers/start_with_country_detector.rb
|
|
103
132
|
- lib/countries/phone_numbers/version.rb
|
|
104
133
|
- spec/countries/country_spec.rb
|
|
134
|
+
- spec/countries/phone_numbers/detector_factory_spec.rb
|
|
105
135
|
- spec/spec_helper.rb
|
|
106
136
|
- spec/test_data.yaml
|
|
107
137
|
homepage: http://github.com/illoyd/countries-phone_numbers
|
|
@@ -130,5 +160,6 @@ specification_version: 4
|
|
|
130
160
|
summary: Integrate phone number searching into the Country gem using Phony
|
|
131
161
|
test_files:
|
|
132
162
|
- spec/countries/country_spec.rb
|
|
163
|
+
- spec/countries/phone_numbers/detector_factory_spec.rb
|
|
133
164
|
- spec/spec_helper.rb
|
|
134
165
|
- spec/test_data.yaml
|