phony 1.9.0 → 2.19.14

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 (82) hide show
  1. checksums.yaml +7 -0
  2. data/README.textile +64 -112
  3. data/lib/phony/config.rb +91 -0
  4. data/lib/phony/countries/argentina.rb +355 -0
  5. data/lib/phony/countries/austria.rb +56 -22
  6. data/lib/phony/countries/bangladesh.rb +57 -0
  7. data/lib/phony/countries/belarus.rb +133 -0
  8. data/lib/phony/countries/brazil.rb +101 -95
  9. data/lib/phony/countries/cambodia.rb +131 -0
  10. data/lib/phony/countries/china.rb +13 -6
  11. data/lib/phony/countries/croatia.rb +23 -0
  12. data/lib/phony/countries/georgia.rb +94 -0
  13. data/lib/phony/countries/germany.rb +66 -42
  14. data/lib/phony/countries/guinea.rb +46 -0
  15. data/lib/phony/countries/india.rb +50 -0
  16. data/lib/phony/countries/indonesia.rb +55 -0
  17. data/lib/phony/countries/ireland.rb +35 -28
  18. data/lib/phony/countries/italy.rb +272 -166
  19. data/lib/phony/countries/japan.rb +468 -0
  20. data/lib/phony/countries/kyrgyzstan.rb +120 -0
  21. data/lib/phony/countries/latvia.rb +43 -0
  22. data/lib/phony/countries/libya.rb +116 -0
  23. data/lib/phony/countries/malaysia.rb +31 -7
  24. data/lib/phony/countries/moldova.rb +53 -0
  25. data/lib/phony/countries/montenegro.rb +30 -0
  26. data/lib/phony/countries/myanmar.rb +55 -0
  27. data/lib/phony/countries/namibia.rb +37 -0
  28. data/lib/phony/countries/nepal.rb +73 -0
  29. data/lib/phony/countries/netherlands.rb +17 -5
  30. data/lib/phony/countries/pakistan.rb +121 -0
  31. data/lib/phony/countries/paraguay.rb +147 -0
  32. data/lib/phony/countries/{russia_kazakhstan_abhasia_south_osetia.rb → russia_kazakhstan_abkhasia_south_ossetia.rb} +35 -24
  33. data/lib/phony/countries/saudi_arabia.rb +40 -0
  34. data/lib/phony/countries/serbia.rb +47 -0
  35. data/lib/phony/countries/somalia.rb +26 -0
  36. data/lib/phony/countries/south_korea.rb +19 -10
  37. data/lib/phony/countries/sweden.rb +58 -38
  38. data/lib/phony/countries/taiwan.rb +28 -0
  39. data/lib/phony/countries/tajikistan.rb +79 -0
  40. data/lib/phony/countries/turkmenistan.rb +76 -0
  41. data/lib/phony/countries/ukraine.rb +630 -0
  42. data/lib/phony/countries/united_kingdom.rb +639 -44
  43. data/lib/phony/countries/uruguay.rb +53 -0
  44. data/lib/phony/countries/vietnam.rb +133 -0
  45. data/lib/phony/countries/zimbabwe.rb +39 -0
  46. data/lib/phony/countries.rb +901 -301
  47. data/lib/phony/country.rb +177 -20
  48. data/lib/phony/country_codes.rb +119 -101
  49. data/lib/phony/dsl.rb +113 -68
  50. data/lib/phony/local_splitters/fixed.rb +25 -1
  51. data/lib/phony/local_splitters/regex.rb +16 -2
  52. data/lib/phony/national_code.rb +7 -7
  53. data/lib/phony/national_splitters/default.rb +35 -3
  54. data/lib/phony/national_splitters/dsl.rb +12 -7
  55. data/lib/phony/national_splitters/fixed.rb +7 -1
  56. data/lib/phony/national_splitters/none.rb +7 -3
  57. data/lib/phony/national_splitters/regex.rb +6 -0
  58. data/lib/phony/national_splitters/variable.rb +13 -9
  59. data/lib/phony/trunk_code.rb +57 -0
  60. data/lib/phony/vanity.rb +3 -3
  61. data/lib/phony.rb +239 -55
  62. data/spec/functional/config_spec.rb +44 -0
  63. data/spec/functional/plausibility_spec.rb +656 -0
  64. data/spec/lib/phony/countries_spec.rb +1207 -119
  65. data/spec/lib/phony/country_codes_spec.rb +99 -81
  66. data/spec/lib/phony/country_spec.rb +54 -14
  67. data/spec/lib/phony/dsl_spec.rb +2 -2
  68. data/spec/lib/phony/local_splitters/fixed_spec.rb +4 -4
  69. data/spec/lib/phony/local_splitters/regex_spec.rb +50 -2
  70. data/spec/lib/phony/national_code_spec.rb +34 -34
  71. data/spec/lib/phony/national_splitters/default_spec.rb +34 -0
  72. data/spec/lib/phony/national_splitters/fixed_spec.rb +12 -6
  73. data/spec/lib/phony/national_splitters/none_spec.rb +13 -3
  74. data/spec/lib/phony/national_splitters/regex_spec.rb +1 -1
  75. data/spec/lib/phony/national_splitters/variable_spec.rb +11 -5
  76. data/spec/lib/phony/trunk_code_spec.rb +85 -0
  77. data/spec/lib/phony/vanity_spec.rb +15 -19
  78. data/spec/lib/phony_spec.rb +59 -277
  79. metadata +67 -34
  80. data/lib/phony/validator.rb +0 -26
  81. data/lib/phony/validators.rb +0 -88
  82. data/spec/lib/phony/validations_spec.rb +0 -109
data/lib/phony/dsl.rb CHANGED
@@ -1,27 +1,3 @@
1
- # # Switzerland (simplified):
2
- # #
3
- # country('41', fixed(2) >> local([3,2,2]))
4
- #
5
- # # Germany. Too big, we use a separate file:
6
- # #
7
- # Phony.define do
8
- # country '49', match(...) >> split([...]) ||
9
- # one_of([...], :max_length => 5) >> split([...])
10
- # end
11
- #
12
- # # Denmark:
13
- # #
14
- # country('45', none >> split([2,2,2,2]))
15
- #
16
- # # Hungary:
17
- # #
18
- # country('36',
19
- # match(/^104|105|107|112/) >> split([3,3]) ||
20
- # one_of([1], :max_length => 2) >> split([3,4])
21
- # )
22
- #
23
- # Note: Perhaps the DSL should operate directly on country codes.
24
- #
25
1
  module Phony
26
2
 
27
3
  # For country definitions.
@@ -36,22 +12,84 @@ module Phony
36
12
  #
37
13
  # Phony.define.country ...
38
14
  #
39
- def self.define
15
+ def self.define(&block)
40
16
  dsl = DSL.new
41
- dsl.instance_eval &Proc.new if block_given?
17
+ dsl.instance_eval(&block) if block_given?
42
18
  dsl
43
19
  end
44
20
 
21
+ # Contains a number of DSL methods. Is used e.g. in the countries.rb file.
22
+ #
23
+ # Do not use directly, but instead use {Phony.define} to execute a block
24
+ # in the DSL instance's context.
25
+ #
26
+ # @example
27
+ # Phony.define { ... }
28
+ #
45
29
  class DSL
46
30
 
47
- # Start defining a country.
31
+ # Define a country's rules.
32
+ #
33
+ # Use the other DSL methods to define the country's rules.
34
+ #
35
+ # @param [String] country_code The country code of the country.
36
+ # @param [Phony::CountryCodes] definition Rules for this country.
37
+ #
38
+ # @return Undefined.
48
39
  #
49
- # Example:
40
+ # @example Add a country with country code 27.
50
41
  # country '27', # CC, followed by rules, for example fixed(2) >> ...
51
42
  #
52
- def country country_code, country, validator = nil
53
- Phony::CountryCodes.instance.add country_code, country
54
- Phony::Validators.instance.add country_code, validator if validator
43
+ def country country_code, definition, options = {}
44
+ return unless Phony.config.load?(country_code)
45
+
46
+ definition.with country_code, options
47
+ Phony::CountryCodes.instance.add country_code, definition
48
+ end
49
+
50
+ # Designates a country code as reserved.
51
+ # A reserved country will result in an exception when trying to be used.
52
+ #
53
+ # @param [String] country_code The country code of the country.
54
+ #
55
+ # @return nil
56
+ #
57
+ # @example Designate country code 27 as reserved.
58
+ # reserved('27')
59
+ #
60
+ def reserved country_code
61
+ # Does nothing, will just fail with an exception.
62
+ end
63
+
64
+ # Define a country to use default rules (and to be done at some point).
65
+ #
66
+ # @return Rules for a country.
67
+ #
68
+ # @example Define country 27 to use default rules.
69
+ # country '27', todo
70
+ #
71
+ def todo
72
+ none >> split(10)
73
+ end
74
+
75
+ # This country uses a trunk code.
76
+ #
77
+ # @param [String] code The trunk code.
78
+ # @param [Hash] options Options hash. Pass :normalize (true/false) to indicate whether it needs to be normalized.
79
+ #
80
+ # @return TrunkCode A trunk code handler.
81
+ #
82
+ # @example Hungary uses 06.
83
+ # country '36', trunk('06', normalize: false) | ...
84
+ #
85
+ # @example North America uses 1.
86
+ # country '1', trunk('1%s', normalize: true) | ...
87
+ #
88
+ # @example Most countries which use a trunk code use 0. E.g. Romania.
89
+ # country '40', trunk('0') | ...
90
+ #
91
+ def trunk code, options = {}
92
+ TrunkCode.new code, options
55
93
  end
56
94
 
57
95
  # National matcher & splitters.
@@ -61,25 +99,24 @@ module Phony
61
99
  # uses a zero prefix when formatted
62
100
  # with format :national.
63
101
  #
64
- # Options:
65
- # * length: Length of the fixed length NDC.
66
- # * options: Set :zero to false to not add a zero on format :national.
102
+ # @param [Fixnum] length The length of the fixed length NDC.
103
+ # @param [Hash] options An options hash (set zero: false to not add a zero on format :national).
67
104
  #
68
- # Example:
69
- # country '33', fixed(1) >> split(2,2,2,2) # France, uses a fixed NDC of size 1.
105
+ # @return NationalSplitters::Fixed A fixed length national splitter.
106
+ #
107
+ # @example France. Uses a fixed NDC of size 1.
108
+ # country '33', fixed(1) >> split(2,2,2,2)
70
109
  #
71
110
  def fixed length, options = {}
72
111
  options[:zero] = true if options[:zero].nil?
73
112
  NationalSplitters::Fixed.instance_for length, options
74
113
  end
75
114
 
76
- # This country does not use an NDC. This rule will always match.
115
+ # Marks the country as not using an NDC. This rule will always match.
116
+ #
117
+ # @return NationalSplitters::None A no-ndc national splitter.
77
118
  #
78
- # Examples:
79
- # * Denmark
80
- # * Norway
81
- # * Iceland
82
- # (and more)
119
+ # @example Denmark, Norway, Iceland.
83
120
  #
84
121
  def none
85
122
  NationalSplitters::None.instance_for
@@ -88,12 +125,14 @@ module Phony
88
125
  # If you have a number of (possibly) variable length NDCs
89
126
  # that cannot be well expressed via regexp, use this.
90
127
  #
91
- # Parameters:
92
- # * ndcs A list of ndcs of variable length.
93
- # * Can contain :max_length => number to denote a maximum NDC length.
128
+ # @param [Array<String>] ndcs A list of NDCs of variable length. Can contain :max_length => number to denote a maximum NDC length.
129
+ #
130
+ # @return NationalSplitters::Variable A variable size national splitter.
94
131
  #
95
- # Example:
96
- # country '51', one_of('103', '105') >> split(3,3) # If it's either 103 or 105, then split ...
132
+ # @example With two NDCs
133
+ # country '51',
134
+ # # If it's either 103 or 105, then split ...
135
+ # one_of('103', '105') >> split(3,3)
97
136
  #
98
137
  def one_of *ndcs
99
138
  options = Hash === ndcs.last ? ndcs.pop : {}
@@ -102,16 +141,17 @@ module Phony
102
141
  #
103
142
  ndcs = ndcs.first if Array === ndcs.first
104
143
 
105
- NationalSplitters::Variable.new options[:max_length], ndcs
144
+ NationalSplitters::Variable.new options[:max_length], ndcs.map(&:freeze)
106
145
  end
107
146
 
108
147
  # If you have a number of (possibly) variable length NDCs
109
148
  # that can be well expressed via regexp, use this.
110
149
  #
111
- # Parameters:
112
- # * regex A regexp describing the NDCs (First group must contain the NDC, eg. /^(0\d{2})\d+$/) contains all NDCs with 0xx...
150
+ # @param [Regexp] regex A Regexp describing the NDCs (First group must contain the NDC, eg. /^(0\d{2})\d+$/) contains all NDCs with 0xx...
113
151
  #
114
- # Example:
152
+ # @return NationalSplitters::Regex A regexp-based national splitter.
153
+ #
154
+ # @example With several NDC matchers.
115
155
  # country '52',
116
156
  # match(/^(0\d{2})\d+$/) >> split(2,2,2,2) |
117
157
  # match(/^(33|55|81)\d+$/) >> split(2,2,2,2) |
@@ -122,43 +162,45 @@ module Phony
122
162
  #
123
163
  raise "Regexp /#{regex.source}/ needs a group in it that defines which digits belong to the NDC." unless regex.source =~ /\(/
124
164
 
125
- on_fail_take = options.delete :on_fail_take
126
165
  NationalSplitters::Regex.instance_for regex, options[:on_fail_take], options
127
166
  end
128
-
129
- # This country still uses a default NDC (and needs to be done, hence the todo).
130
- #
131
- def todo
132
- none >> NationalSplitters::Default.instance_for
133
- end
134
167
 
135
168
  # Local splitters.
136
169
  #
137
170
 
138
171
  # Splits the number into groups of given sizes.
139
172
  #
140
- # Example:
173
+ # Also takes ranges.
174
+ #
175
+ # @param [Array<Fixnum>] local The local group sizes to split the local number part into.
176
+ #
177
+ # @return LocalSplitters::Fixed A fixed size local splitter.
178
+ #
179
+ # @example Splitting in 4 even groups of two digits.
141
180
  # match(/^(0\d{2})\d+$/) >> split(2,2,2,2) # If it matches, split in 4 groups of size 2.
142
181
  #
143
182
  def split *local
144
- local << local.pop + 10 # Allow for call-through numbers with an arbitrary size.
183
+ # local << local.pop + 10 # Allow for call-through numbers with an arbitrary size.
145
184
  LocalSplitters::Fixed.instance_for local
146
185
  end
147
186
 
148
187
  # Matches on the rest of the number and splits according
149
188
  # to the given value for the regexp key.
150
189
  #
151
- # Options:
152
- # * fallback A fallback amount of group sizes in case it doesn't match.
190
+ # Also takes ranges.
191
+ #
192
+ # @param [Hash] options Can contain option :fallback A fallback amount of group sizes in case it doesn't match.
193
+ #
194
+ # @return LocalSplitters::Regex A regexp-based local splitter.
153
195
  #
154
- # Example:
196
+ # @example Norway
155
197
  # country '47',
156
198
  # none >> matched_split(/^[1].*$/ => [3],
157
199
  # /^[489].*$/ => [3,2,3],
158
200
  # :fallback => [2,2,2,2])
159
201
  #
160
202
  def matched_split options = {}
161
- Phony::LocalSplitters::Regex.instance_for options
203
+ LocalSplitters::Regex.instance_for options
162
204
  end
163
205
 
164
206
  # Validators
@@ -166,17 +208,20 @@ module Phony
166
208
 
167
209
  # Which NDCs are explicitly invalid?
168
210
  #
169
- # Takes a regexp or a string.
211
+ # @param [Regexp, String] ndc A regexp or a string of invalid NDCs.
170
212
  #
171
- # Example:
213
+ # @return Validators::NDC An NDC validator
214
+ #
215
+ # @example NANP
172
216
  # country '1',
173
217
  # fixed(3, :zero => false) >> split(3,4),
174
218
  # invalid_ndcs('911') # The regexp /911/ would also work.
175
219
  #
176
- def invalid_ndcs ndc
177
- Validator.new.ndc_check ndc
220
+ def invalid_ndcs *ndc
221
+ Validators::NDC.new invalid: ndc
178
222
  end
179
223
 
224
+
180
225
  end
181
226
 
182
227
  end
@@ -27,7 +27,23 @@ module Phony
27
27
  # The format [3, 2, 2] splits a number like '3332222' into ['333', '22', '22'].
28
28
  #
29
29
  def initialize format = nil
30
- @format = format || [3, 2, 2]
30
+ format = format && format.dup || [3, 2, 2]
31
+ @format, @length = extract_params format
32
+ @format << @format.pop + 10
33
+ end
34
+
35
+ #
36
+ #
37
+ def extract_params format
38
+ if format.last.respond_to? :max
39
+ last = format.pop
40
+ length = format.inject(0) { |total, part| total + part }
41
+ length = (length+last.min..length+last.max)
42
+ format << last.min
43
+ else
44
+ length = format.inject(0) { |total, part| total + part }
45
+ end
46
+ [format, length]
31
47
  end
32
48
 
33
49
  # Split a local number according to an assumed country specific format.
@@ -43,6 +59,14 @@ module Phony
43
59
  end
44
60
  end
45
61
 
62
+ #
63
+ #
64
+ def plausible? rest, hints = {}
65
+ return true if hints[:check_length] == false
66
+
67
+ @length === rest.inject(0) { |total, part| total + part.size }
68
+ end
69
+
46
70
  end
47
71
 
48
72
  end
@@ -42,6 +42,15 @@ module Phony
42
42
  split_with number, fallback
43
43
  end
44
44
 
45
+ def plausible? rest, hints = {}
46
+ number = rest.inject('', :+)
47
+ mapping.each do |regex, format|
48
+ next unless number =~ regex
49
+ return plausible_with? number, format
50
+ end
51
+ plausible_with? number, fallback
52
+ end
53
+
45
54
  private
46
55
 
47
56
  def split_with number, format
@@ -49,9 +58,14 @@ module Phony
49
58
  result << number.slice!(0..size-1)
50
59
  return result if number.empty?
51
60
  result
52
- end
61
+ end << number
53
62
  end
54
-
63
+
64
+ def plausible_with? number, format
65
+ length = format.inject 0, :+
66
+ number.length == length
67
+ end
68
+
55
69
  end
56
70
 
57
71
  end
@@ -3,13 +3,14 @@ module Phony
3
3
  # NationalCodes have a special numbers splitter, a national code splitter and a local code splitter.
4
4
  #
5
5
  class NationalCode
6
-
6
+
7
+ attr_reader :local_splitter
8
+
7
9
  #
8
10
  #
9
- def initialize national_splitter, local_splitter, normalize = nil
11
+ def initialize national_splitter, local_splitter
10
12
  @national_splitter = national_splitter
11
13
  @local_splitter = local_splitter
12
- @normalize = normalize != false
13
14
  end
14
15
 
15
16
  # Split gets a number without country code and splits it into
@@ -25,11 +26,10 @@ module Phony
25
26
  #
26
27
  # Note: Some cases, like Italy, don't remove the relative zero.
27
28
  #
28
- def normalize national_number
29
- return national_number unless @normalize
30
- national_number.gsub(/^0+/, '')
29
+ def normalize national_number, options = {}
30
+ national_number.gsub(/\A0+/, EMPTY_STRING)
31
31
  end
32
32
 
33
33
  end
34
34
 
35
- end
35
+ end
@@ -1,15 +1,47 @@
1
1
  module Phony
2
2
 
3
3
  module NationalSplitters
4
-
4
+
5
+ # TODO Default = Fixed.new(...)?
6
+ #
5
7
  class Default < DSL
6
8
 
7
9
  def self.instance_for
8
10
  @instance ||= new
9
11
  end
10
-
12
+
13
+ # "Splits" the national part of a phone number into a single piece.
14
+ #
15
+ # @param [String] national_number An national part of a number.
16
+ #
17
+ # @return [Array<String>] An Array with the given number part as its element.
18
+ #
19
+ # @example Split the national part of a Swiss number.
20
+ # Phony.split("1234567") # => ["1234567"]
21
+ #
11
22
  def split national_number
12
- [national_number]
23
+ [nil, national_number]
24
+ end
25
+
26
+ # By default, the national part of a number is always plausible.
27
+ #
28
+ # @param [String] rest An national part of a number (ignored).
29
+ # @param [Fixnum] size Size (ignored).
30
+ # @param [Hash] hints Hints (ignored).
31
+ #
32
+ # @return [Boolean] Always true.
33
+ #
34
+ # @example Split the national part of a Swiss number.
35
+ # Phony.plausible?("1234567") # => true
36
+ #
37
+ def plausible? rest, size, hints = {}
38
+ true
39
+ end
40
+
41
+ # A valid length (at least 3).
42
+ #
43
+ def length
44
+ 3
13
45
  end
14
46
 
15
47
  end
@@ -9,15 +9,20 @@ module Phony
9
9
  #
10
10
  #
11
11
  def >> local_splitter
12
- country_for local_splitter, true
12
+ country_for local_splitter
13
13
  end
14
14
 
15
- private
16
-
17
- def country_for local_splitter, with_zero
18
- national_code = Phony::NationalCode.new self, local_splitter, with_zero
19
- Phony::Country.new national_code
20
- end
15
+ #
16
+ #
17
+ def country_for local_splitter
18
+ Phony::Country.new Phony::NationalCode.new(self, local_splitter)
19
+ end
20
+
21
+ # TODO Remove?
22
+ #
23
+ def reserved
24
+
25
+ end
21
26
 
22
27
  end
23
28
 
@@ -20,7 +20,7 @@ module Phony
20
20
 
21
21
  def initialize size, options = {}
22
22
  @size = size
23
- @zero = options[:zero] == false ? nil : '0'
23
+ @zero = nil # options[:zero] == false ? nil : '0'
24
24
  end
25
25
 
26
26
  # Takes a national number and splits it into ndc and rest.
@@ -30,6 +30,12 @@ module Phony
30
30
  [@zero, national_number.slice!(0...@size), national_number]
31
31
  end
32
32
 
33
+ # A valid length.
34
+ #
35
+ def length
36
+ @size
37
+ end
38
+
33
39
  end
34
40
 
35
41
  end
@@ -31,14 +31,18 @@ module Phony
31
31
  # since using nil is dangerous and breaks
32
32
  # abstraction)
33
33
  #
34
- # Note: Actually, it might stay in.
35
- #
36
- # TODO Flip nil/false?
34
+ # Note: Decided it stays in. When formatting, it's turned into nil.
37
35
  #
38
36
  def split national_number
39
37
  [nil, false, national_number]
40
38
  end
41
39
 
40
+ # A valid length.
41
+ #
42
+ def length
43
+ 0
44
+ end
45
+
42
46
  end
43
47
 
44
48
  end
@@ -42,6 +42,12 @@ module Phony
42
42
  super national_number
43
43
  end
44
44
 
45
+ # A valid length.
46
+ #
47
+ def length
48
+ # raise "#{self.class.name} has no length that can be automatically extracted."
49
+ end
50
+
45
51
  end
46
52
 
47
53
  end
@@ -18,17 +18,19 @@ module Phony
18
18
 
19
19
  # Extract a starting point.
20
20
  #
21
+ # This if can possibly be removed.
22
+ #
21
23
  presumed_code = if @mapped_ndc_min_length > 0
22
- national_number.slice!(0..@mapped_ndc_min_length-1)
24
+ presumed_code = national_number.slice!(0..@mapped_ndc_min_length-1)
23
25
  else
24
26
  ''
25
27
  end
26
28
 
27
29
  # Try for all possible mapped.
28
30
  #
29
- @mapped_ndc_min_length.upto(@mapped_ndc_max_length) do |i|
30
- sized_ndcs = @ndcs[i]
31
- return [@zero, presumed_code, national_number] unless sized_ndcs && !sized_ndcs.include?(presumed_code)
31
+ @mapped_ndc_min_length.upto @mapped_ndc_max_length do |i|
32
+ ndcs_of_size_i = @ndcs[i]
33
+ return [@zero, presumed_code, national_number] unless ndcs_of_size_i && !ndcs_of_size_i.include?(presumed_code)
32
34
  presumed_code << national_number.slice!(0..0)
33
35
  end
34
36
 
@@ -37,15 +39,17 @@ module Phony
37
39
  super fallback_number
38
40
  end
39
41
 
42
+ # A valid length.
43
+ #
44
+ def length
45
+ (@mapped_ndc_min_length..@mapped_ndc_max_length)
46
+ end
47
+
40
48
  private
41
49
 
42
- # def restructure ndc_map
43
- # optimize ndc_map.values.flatten
44
- # end
45
-
46
50
  # Optimizes and restructures the given ndcs array.
47
51
  #
48
- def optimize(ndc_ary)
52
+ def optimize ndc_ary
49
53
  ndcs = {}
50
54
  ndc_ary.each do |ndc|
51
55
  ndcs[ndc.length] ||= []
@@ -0,0 +1,57 @@
1
+ module Phony
2
+
3
+ class TrunkCode
4
+
5
+ # Parameters:
6
+ # * code: The trunk code, e.g. 0.
7
+ #
8
+ # Options:
9
+ # * normalize: [true (default), false] Remove the trunk code when normalizing (only use if number scheme is defined unambiguously).
10
+ # * split: [true, false (default)] Remove the trunk code when splitting (only use if number scheme is defined unambiguously).
11
+ # * format: [true (default), false] Add the trunk code when formatting (passing `false` will not add it).
12
+ #
13
+ def initialize code, options = {}
14
+ @code = code
15
+ @trunk_code_replacement = /\A#{code.gsub(%r{%s}, '')}/
16
+ @normalize = options[:normalize] || options[:normalize].nil?
17
+ @split = options[:split]
18
+ @format = options[:format] || options[:format].nil?
19
+ end
20
+
21
+ # Prepends itself to the other codes.
22
+ #
23
+ def | other
24
+ other.codes.unshift self
25
+ other
26
+ end
27
+
28
+ # Split gets a number without country code and splits it into
29
+ # its parts.
30
+ #
31
+ def split national_number
32
+ national_number.gsub! @trunk_code_replacement, EMPTY_STRING if @split
33
+ return [self, national_number]
34
+ end
35
+
36
+ # Normalize normalizes the given national number.
37
+ #
38
+ def normalize national_number, options = {}
39
+ national_number.gsub! @trunk_code_replacement, EMPTY_STRING if @normalize && options[:cc]
40
+ return national_number
41
+ end
42
+
43
+ # Format the trunk code using the spaces given.
44
+ #
45
+ def format space, force = nil
46
+ if force || @format
47
+ if @code.size > 1
48
+ (@code % space).gsub(/\D/, ' ')
49
+ else
50
+ @code
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
data/lib/phony/vanity.rb CHANGED
@@ -16,11 +16,11 @@ module Phony
16
16
  # Replaces (and normalizes) vanity characters of passed number with correct digits.
17
17
  #
18
18
  def self.replace number
19
- number.tr *mapping
19
+ number.tr(*mapping)
20
20
  end
21
21
 
22
22
  # Returns true if there is a character in the number
23
- # after the first four numbers.
23
+ # after the first three numbers.
24
24
  #
25
25
  @@vanity_regexp = /\A\d{3}[a-zA-Z]{6,12}\Z/
26
26
  def self.vanity? number
@@ -29,7 +29,7 @@ module Phony
29
29
 
30
30
  # Vanity-Normalized.
31
31
  #
32
- @@vanity_normalizing_regexp = /^0*|[^\d\w]/
32
+ @@vanity_normalizing_regexp = /^0*|[^\w]/
33
33
  def self.normalized number
34
34
  number.gsub @@vanity_normalizing_regexp, ''
35
35
  end