phony 1.2.11 → 1.3.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.
Files changed (49) hide show
  1. data/README.textile +1 -1
  2. data/lib/countries.rb +385 -0
  3. data/lib/phony.rb +11 -9
  4. data/lib/phony/countries.rb +1 -0
  5. data/lib/phony/countries/austria.rb +68 -67
  6. data/lib/phony/countries/belgium.rb +29 -57
  7. data/lib/phony/countries/chile.rb +5 -12
  8. data/lib/phony/countries/china.rb +21 -20
  9. data/lib/phony/countries/egypt.rb +12 -37
  10. data/lib/phony/countries/germany.rb +39 -36
  11. data/lib/phony/countries/greece.rb +21 -25
  12. data/lib/phony/countries/hungary.rb +6 -19
  13. data/lib/phony/countries/italy.rb +174 -152
  14. data/lib/phony/countries/malaysia.rb +17 -17
  15. data/lib/phony/countries/netherlands.rb +50 -52
  16. data/lib/phony/countries/romania.rb +28 -27
  17. data/lib/phony/countries/south_korea.rb +11 -11
  18. data/lib/phony/countries/sweden.rb +49 -49
  19. data/lib/phony/countries/united_kingdom.rb +4 -4
  20. data/lib/phony/country.rb +14 -80
  21. data/lib/phony/country_codes.rb +23 -3
  22. data/lib/phony/dsl.rb +78 -0
  23. data/lib/phony/national_code.rb +2 -5
  24. data/lib/phony/national_splitters/dsl.rb +20 -0
  25. data/lib/phony/national_splitters/fixed.rb +1 -1
  26. data/lib/phony/national_splitters/none.rb +1 -1
  27. data/lib/phony/national_splitters/regex.rb +49 -0
  28. data/lib/phony/national_splitters/variable.rb +6 -6
  29. data/lib/phony/vanity.rb +3 -0
  30. data/spec/lib/phony/country_codes_spec.rb +1 -1
  31. data/spec/lib/phony/country_spec.rb +12 -45
  32. data/spec/lib/phony/local_splitters/fixed_spec.rb +8 -0
  33. data/spec/lib/phony/national_code_spec.rb +13 -0
  34. data/spec/lib/phony/national_splitters/regex_spec.rb +23 -0
  35. data/spec/lib/phony/national_splitters/variable_spec.rb +2 -4
  36. data/spec/lib/phony_spec.rb +44 -4
  37. metadata +9 -21
  38. data/lib/phony/countries/all_other.rb +0 -455
  39. data/lib/phony/countries/norway.rb +0 -11
  40. data/lib/phony/countries/peru.rb +0 -19
  41. data/lib/phony/countries/portugal.rb +0 -16
  42. data/lib/phony/national_splitters/experimental.rb +0 -17
  43. data/spec/lib/phony/countries/austria_spec.rb +0 -24
  44. data/spec/lib/phony/countries/belgium_spec.rb +0 -33
  45. data/spec/lib/phony/countries/egypt_spec.rb +0 -18
  46. data/spec/lib/phony/countries/greece_spec.rb +0 -18
  47. data/spec/lib/phony/countries/portugal_spec.rb +0 -21
  48. data/spec/lib/phony/countries/switzerland_spec.rb +0 -18
  49. data/spec/lib/phony/countries/united_kingdom_spec.rb +0 -50
@@ -4,6 +4,12 @@ module Phony
4
4
  #
5
5
  class CountryCodes
6
6
 
7
+ attr_reader :mapping
8
+
9
+ def self.instance
10
+ @instance ||= new
11
+ end
12
+
7
13
  def normalize number
8
14
  # Remove non-digit chars.
9
15
  #
@@ -44,6 +50,8 @@ module Phony
44
50
  parts_ary.join space.to_s
45
51
  end
46
52
 
53
+ #
54
+ #
47
55
  def service? number
48
56
  national_handler, cc, rest = split_cc number
49
57
  national_handler.service? rest
@@ -80,10 +88,22 @@ module Phony
80
88
  # This line is never reached as CCs are in prefix code.
81
89
  end
82
90
 
83
- # Cached mapping of all countries.
91
+ # # TODO
92
+ # #
93
+ # def self.with_cc cc
94
+ # mapping[cc.size][cc.to_s]
95
+ # end
96
+
97
+ # Add the given country to the mapping under the
98
+ # given country code.
84
99
  #
85
- def mapping
86
- @mapping ||= Phony::Countries.mapping
100
+ def add country_code, country
101
+ country_code = country_code.to_s
102
+ optimized_country_code_access = country_code.size
103
+
104
+ @mapping ||= {}
105
+ @mapping[optimized_country_code_access] ||= {}
106
+ @mapping[optimized_country_code_access][country_code] = country
87
107
  end
88
108
 
89
109
  end
data/lib/phony/dsl.rb ADDED
@@ -0,0 +1,78 @@
1
+ # # Ideas for a DSL:
2
+ # #
3
+ #
4
+ # # Switzerland
5
+ # #
6
+ # country('41', fixed(2) >> local([3,2,2]))
7
+ # country(match(/^1.*$/) >> [3,3] || none >> [2,2,2,2])
8
+ #
9
+ # # Germany. Too big.
10
+ # #
11
+ # country('49', Countries::Germany)
12
+ # #
13
+ # # … and in Germany:
14
+ # #
15
+ # include Phony::DSL
16
+ # Countries::Germany = match(...) >> split([...]) ||
17
+ # one_of([...], :max_length => 5) >> split([...])
18
+ #
19
+ # # Denmark.
20
+ # #
21
+ # country('45', none >> split([2,2,2,2])) # Denmark.
22
+ #
23
+ # # Hungary.
24
+ # #
25
+ # country('36',
26
+ # match(/^104|105|107|112/) >> split([3,3]) ||
27
+ # one_of([1], :max_length => 2) >> split([3,4])
28
+ # )
29
+
30
+ module Phony
31
+
32
+ module DSL
33
+
34
+ #
35
+ #
36
+ def country country_code, country
37
+ Phony::CountryCodes.instance.add country_code, country
38
+ end
39
+
40
+ # National matcher & splitters.
41
+ #
42
+
43
+ #
44
+ #
45
+ def fixed size
46
+ NationalSplitters::Fixed.instance_for size
47
+ end
48
+ def none
49
+ NationalSplitters::None.instance_for
50
+ end
51
+ def one_of *ndcs
52
+ options = Hash === ndcs.last ? ndcs.pop : {}
53
+
54
+ # Ruby 1.8 compatibility mode.
55
+ #
56
+ ndcs = ndcs.first if Array === ndcs.first
57
+
58
+ NationalSplitters::Variable.new options[:max_length], ndcs
59
+ end
60
+ def match regex, options = {}
61
+ NationalSplitters::Regex.instance_for regex, options[:on_fail_take]
62
+ end
63
+
64
+ # Local splitters.
65
+ #
66
+
67
+ #
68
+ #
69
+ def split *local
70
+ LocalSplitters::Fixed.instance_for local
71
+ end
72
+ def matched_split options = {}
73
+ Phony::LocalSplitters::Regex.instance_for options
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -1,7 +1,5 @@
1
1
  module Phony
2
2
 
3
- # This is the superclass of all special national number handlers.
4
- #
5
3
  # NationalCodes have a special numbers splitter, a national code splitter and a local code splitter.
6
4
  #
7
5
  class NationalCode
@@ -11,7 +9,7 @@ module Phony
11
9
  def initialize national_splitter, local_splitter, normalize = nil
12
10
  @national_splitter = national_splitter
13
11
  @local_splitter = local_splitter
14
- @normalize = !(normalize == false) # if nil, true (default), if false, false, if true, true.
12
+ @normalize = normalize != false
15
13
  end
16
14
 
17
15
  # Split gets a number without country code and splits it into
@@ -20,8 +18,7 @@ module Phony
20
18
  def split national_number
21
19
  ndc, rest = @national_splitter.split national_number.dup
22
20
  return ndc unless rest
23
- local = @local_splitter.split rest
24
- ndc ? [ndc, *local] : local
21
+ [ndc, *@local_splitter.split(rest)]
25
22
  end
26
23
 
27
24
  # Split gets a number without country code and removes a relative zero.
@@ -0,0 +1,20 @@
1
+ module Phony
2
+
3
+ module NationalSplitters
4
+
5
+ # TODO
6
+ #
7
+ class DSL
8
+
9
+ # TODO normalize option!
10
+ #
11
+ def >> local_splitter
12
+ national_code = Phony::NationalCode.new self, local_splitter
13
+ Phony::Country.new national_code
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -4,7 +4,7 @@ module Phony
4
4
 
5
5
  # TODO
6
6
  #
7
- class Fixed < Experimental
7
+ class Fixed < DSL
8
8
 
9
9
  attr_writer :special_splitter
10
10
 
@@ -5,7 +5,7 @@ module Phony
5
5
  # This is a national splitter for countries
6
6
  # which have no NDC / Area Code.
7
7
  #
8
- class None < Experimental
8
+ class None < DSL
9
9
 
10
10
  # Get a splitter. Caches.
11
11
  #
@@ -0,0 +1,49 @@
1
+ module Phony
2
+
3
+ module NationalSplitters
4
+
5
+ # National splitter class to split the ndc-local part of a number.
6
+ #
7
+ # Countries can create new instances according to their needs.
8
+ #
9
+ # Note: Countries should use instance_for
10
+ # to avoid getting new local splitter instances.
11
+ #
12
+ class Regex < Fixed
13
+
14
+ attr_reader :on_fail_take, :regex
15
+
16
+ # Get a splitter for the given format.
17
+ #
18
+ # Note: Not cached.
19
+ #
20
+ def self.instance_for regex, on_fail_take = nil
21
+ new regex, on_fail_take
22
+ end
23
+
24
+ def initialize regex, on_fail_take = nil
25
+ super on_fail_take
26
+
27
+ @regex = regex
28
+ end
29
+
30
+ # Split a local number according to an assumed country specific format.
31
+ #
32
+ # Examples
33
+ # * split '3643533' # => ['364', '35', '33'] # (Switzerland)
34
+ #
35
+ def split number
36
+ # Improve matching.
37
+ #
38
+ return [number.slice!(0..$1.size-1), number] if number =~ regex
39
+
40
+ # Not found.
41
+ #
42
+ super number
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -6,9 +6,9 @@ module Phony
6
6
 
7
7
  #
8
8
  #
9
- def initialize fallback, ndc_map
9
+ def initialize fallback, ndcs
10
10
  super fallback
11
- @ndcs = restructure ndc_map
11
+ @ndcs = optimize ndcs
12
12
  end
13
13
 
14
14
  # Takes a national number and splits it into ndc and rest.
@@ -34,14 +34,14 @@ module Phony
34
34
 
35
35
  # Not found.
36
36
  #
37
- return super(fallback_number)
37
+ super fallback_number
38
38
  end
39
39
 
40
40
  private
41
41
 
42
- def restructure ndc_map
43
- optimize ndc_map.values.flatten
44
- end
42
+ # def restructure ndc_map
43
+ # optimize ndc_map.values.flatten
44
+ # end
45
45
 
46
46
  # Optimizes and restructures the given ndcs array.
47
47
  #
data/lib/phony/vanity.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  module Phony
2
+
3
+ # Helper module that maps vanity numbers to digit numbers.
4
+ #
2
5
  module Vanity
3
6
 
4
7
  # Returns a char to number mapping string for the String#tr method.
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Phony::CountryCodes do
4
4
 
5
5
  before(:all) do
6
- @countries = Phony::CountryCodes.new
6
+ @countries = Phony::CountryCodes.instance
7
7
  end
8
8
 
9
9
  describe 'split' do
@@ -2,57 +2,24 @@ require 'spec_helper'
2
2
 
3
3
  describe Phony::Country do
4
4
 
5
- describe "configured" do
6
- context "with variable ndcs" do
5
+ context 'regression' do
6
+ describe 'iceland' do
7
7
  before(:each) do
8
- @country = Phony::Country.configured :local_format => [3, 2, 2],
9
- :service_local_format => [3, 3],
10
- :mobile_local_format => [1, 2, 4],
11
- :ndc_fallback_length => 4,
12
- :ndc_mapping => {
13
- :normal => ['44'],
14
- :service => ['800'],
15
- :mobile => ['76']
16
- }
17
- end
18
- it 'works for normal numbers' do
19
- @country.split('443643532').should == ['44', '364', '35', '32']
20
- end
21
- it 'works with service numbers' do
22
- @country.split('800333666').should == ['800', '333', '666']
23
- end
24
- it 'works with mobile numbers' do
25
- @country.split('764333532').should == ['76', '4', '33', '3532']
26
- end
27
- it 'uses the fallback if it is not in the mapping' do
28
- @country.split('123456789').should == ['1234', '567', '89']
29
- end
30
- end
31
- context "with fixed ndcs" do
32
- before(:each) do
33
- @country = Phony::Country.fixed :ndc_length => 2,
34
- :local_format => [3, 2, 2],
35
- :service_local_format => [3, 3],
36
- :service_ndcs => ['800']
37
- end
38
- it 'works for non-service numbers' do
39
- @country.split('443643532').should == ['44', '364', '35', '32']
40
- end
41
- it 'works for service numbers' do
42
- @country.split('800333666').should == ['800', '333', '666']
43
- end
44
- it 'works with mobile numbers' do
45
- @country.split('764333532').should == ['76', '433', '35', '32']
8
+ national_splitter = Phony::NationalSplitters::None.instance_for
9
+ local_splitter = Phony::LocalSplitters::Fixed.instance_for [3, 4]
10
+
11
+ national_code = Phony::NationalCode.new national_splitter, local_splitter
12
+ @iceland = described_class.new national_code
46
13
  end
47
- it 'uses a fixed length' do
48
- @country.split('123456789').should == ['12', '345', '67', '89']
14
+ it 'splits correctly' do
15
+ @iceland.split('112').should == ['112']
49
16
  end
50
17
  end
51
18
  end
52
19
 
53
20
  context "without special cases" do
54
21
  before(:each) do
55
- national_splitter = Phony::NationalSplitters::Variable.new 4, { :normal => ['44'] }
22
+ national_splitter = Phony::NationalSplitters::Variable.new 4, ['44']
56
23
  local_splitter = Phony::LocalSplitters::Fixed.instance_for [3, 2, 2]
57
24
  national_code = Phony::NationalCode.new national_splitter, local_splitter
58
25
 
@@ -73,11 +40,11 @@ describe Phony::Country do
73
40
 
74
41
  context "without special cases" do
75
42
  before(:each) do
76
- special_national_splitter = Phony::NationalSplitters::Variable.new nil, { :service => ['800'] }
43
+ special_national_splitter = Phony::NationalSplitters::Variable.new nil, ['800']
77
44
  special_local_splitter = Phony::LocalSplitters::Fixed.instance_for [3, 3]
78
45
  special_code = Phony::NationalCode.new special_national_splitter, special_local_splitter
79
46
 
80
- national_splitter = Phony::NationalSplitters::Variable.new 4, { :normal => ['44'] }
47
+ national_splitter = Phony::NationalSplitters::Variable.new 4, ['44']
81
48
  local_splitter = Phony::LocalSplitters::Fixed.instance_for [3, 2, 2]
82
49
  national_code = Phony::NationalCode.new national_splitter, local_splitter
83
50
 
@@ -43,6 +43,14 @@ describe Phony::LocalSplitters::Fixed do
43
43
  @splitter.split('364353').should == ['364','35','3']
44
44
  end
45
45
  end
46
+ context "with hard number (iceland regression)" do
47
+ before(:each) do
48
+ @splitter = described_class.new [3, 4]
49
+ end
50
+ it 'splits correctly' do
51
+ @splitter.split('112').should == ['112']
52
+ end
53
+ end
46
54
  end
47
55
 
48
56
  end
@@ -3,6 +3,19 @@ require 'spec_helper'
3
3
  describe Phony::NationalCode do
4
4
 
5
5
  describe 'split' do
6
+ context 'regression' do
7
+ describe 'iceland' do
8
+ before(:each) do
9
+ national_splitter = Phony::NationalSplitters::None.instance_for
10
+ local_splitter = Phony::LocalSplitters::Fixed.instance_for [3, 4]
11
+
12
+ @national = Phony::NationalCode.new national_splitter, local_splitter
13
+ end
14
+ it 'splits correctly' do
15
+ @national.split('112').should == [nil, '112']
16
+ end
17
+ end
18
+ end
6
19
  context 'with fixed ndc (Swiss)' do
7
20
  before(:each) do
8
21
  national_splitter = Phony::NationalSplitters::Fixed.instance_for 2
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Phony::NationalSplitters::Regex do
4
+
5
+ describe 'instance_for' do
6
+ it 'caches correctly (not)' do
7
+ described_class.instance_for(//).should_not equal(described_class.instance_for(//))
8
+ end
9
+ end
10
+
11
+ describe 'split' do
12
+ context 'without on_fail' do
13
+ let(:splitter) { described_class.instance_for(/^(123)\d+$/) }
14
+ end
15
+ context 'with on_fail 2' do
16
+ let(:splitter) { described_class.instance_for(/^(123)\d+$/, 2) }
17
+ it 'uses the on_fail_take' do
18
+ splitter.split('23456789').should == ['23', '456789']
19
+ end
20
+ end
21
+ end
22
+
23
+ end
@@ -5,9 +5,7 @@ describe Phony::NationalSplitters::Variable do
5
5
  describe 'split' do
6
6
  context 'normal' do
7
7
  before(:each) do
8
- @splitter = Phony::NationalSplitters::Variable.new 4, :normal => ['1', '316'],
9
- :mobile => ['67', '68',],
10
- :service => ['669', '711']
8
+ @splitter = Phony::NationalSplitters::Variable.new 4, ['1', '316', '67', '68', '669', '711']
11
9
  end
12
10
  it "handles Vienna" do
13
11
  @splitter.split('198110').should == ['1', '98110']
@@ -24,7 +22,7 @@ describe Phony::NationalSplitters::Variable do
24
22
  end
25
23
  context 'special handling for using the variable size splitter for Swiss service numbers' do
26
24
  before(:each) do
27
- @splitter = Phony::NationalSplitters::Variable.new 2, :service => ['800']
25
+ @splitter = Phony::NationalSplitters::Variable.new 2, ['800']
28
26
  end
29
27
  it "should handle swiss service numbers" do
30
28
  @splitter.split('800223344').should == ['800', '223344']