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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d299eda3bc0d2e84c08d735a501c4c47398964c
4
- data.tar.gz: b33baf81c54d96734b71fc0f82383d35704e4b12
3
+ metadata.gz: 86db77726a2eb98b11c2aef026b1d121d3dcd184
4
+ data.tar.gz: b0083df537fe9839eb25f25a1a19148d4b581e2d
5
5
  SHA512:
6
- metadata.gz: 68f5972c6d39e1106b576408360cbdb69c4cdcd81c56af2e7a85193b41edc22dc6af128ae05c6a4d519f96b124bc8b90c30a0bd58e2081431cf28cf44cc79c65
7
- data.tar.gz: 42d5ee3f67a0874ec07b5a303be69a1a172b590e7c724e45c67e988b3073f4a672e3ebadd8afc1f65d0d1900fa763766ff8539ac88ce2d0dd2b6576a82851a17
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
@@ -8,7 +8,7 @@ class ISO3166::Country
8
8
  end
9
9
 
10
10
  def self.tokenize_phone_number( number )
11
- Phony.split( Phony.normalize( number ) )
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 = phone_number_detectors[normalised_number.first]
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 self.find_all_by_country_code( normalised_number.first )
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 = phone_number_detector_for normalised_number.first
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 self.find_all_countries_by_country_code( normalised_number.first )
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.phone_number_detectors.keys.include? key or key == '' }
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
- # Collection of country detectors. Detectors are instantiated only when first needed.
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
@@ -1,5 +1,5 @@
1
1
  module Countries
2
2
  module PhoneNumbers
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -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
@@ -1,5 +1,10 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
+ require 'json'
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+
3
8
  require 'countries/phone_numbers'
4
9
 
5
10
  require 'yaml'
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.1
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-01 00:00:00.000000000 Z
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/country_detectors.yaml
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