countries-phone_numbers 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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