phony 1.9.0 → 2.19.14

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