phonelib 0.6.21 → 0.7.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 +5 -5
- data/README.md +61 -5
- data/Rakefile +7 -0
- data/data/extended_data.dat +0 -0
- data/data/phone_data.dat +0 -0
- data/lib/phonelib/core.rb +85 -0
- data/lib/phonelib/data_importer.rb +68 -1
- data/lib/phonelib/data_importer_helper.rb +1 -0
- data/lib/phonelib/phone.rb +13 -1
- data/lib/phonelib/phone_analyzer.rb +27 -6
- data/lib/phonelib/phone_analyzer_helper.rb +15 -2
- data/lib/phonelib/phone_extended_data.rb +10 -3
- data/lib/phonelib/phone_formatter.rb +33 -14
- data/lib/phonelib/version.rb +1 -1
- data/lib/phonelib.rb +5 -1
- data/lib/validators/phone_validator.rb +46 -23
- data/lib/validators/phone_validator3.rb +130 -0
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d9a96a615d554195979c6dc886188eb4f8638e89f616fb5ce5aa6cb74ee91ca0
|
4
|
+
data.tar.gz: e8b51d76743373fd9e2913eb5eddcea65e35e57673f29e47a361398dab662a16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7710f2ab513e1bb53bb6bec2fe78de93fa742c18c85f2393f05ebf862cd245c7b3b01a4055403af287c4e225a58c26fd03507f0f08bf9e4d1468ad1279623ecd
|
7
|
+
data.tar.gz: e44959fbc033b27ac6b2974941c2ce010ba788bf371a4048a45c7d3dba78bb982b08c9201019b4bd2f958b139e46f7f29dcf0c0ae6c406a94d21490129df68de
|
data/README.md
CHANGED
@@ -2,16 +2,20 @@
|
|
2
2
|
|
3
3
|
[](https://www.jetbrains.com/ruby/)
|
4
4
|
[](http://badge.fury.io/rb/phonelib)
|
5
|
-
[](https://circleci.com/gh/daddyz/phonelib/tree/master)
|
6
6
|
[](https://codeclimate.com/github/daddyz/phonelib/coverage)
|
7
7
|
[](https://codeclimate.com/github/daddyz/phonelib)
|
8
|
-
[](https://gemnasium.com/daddyz/phonelib)
|
9
8
|
[](http://inch-ci.org/github/daddyz/phonelib)
|
10
9
|
|
11
10
|
Phonelib is a gem allowing you to validate phone number. All validations are based on [Google libphonenumber](https://github.com/googlei18n/libphonenumber).
|
12
11
|
Currently it can make basic validations and formatting to e164 international number format and national number format with prefix.
|
13
12
|
But it still doesn't include all Google's library functionality.
|
14
13
|
|
14
|
+
## Incorrect parsing or validation
|
15
|
+
|
16
|
+
In case your phone number is incorrectly parsed, you can check original libphonenumber for result [here](https://rawgit.com/googlei18n/libphonenumber/master/javascript/i18n/phonenumbers/demo-compiled.html) and in case of same parse result [open an issue for them](https://issuetracker.google.com/issues/new?component=192347&template=829703). This gem's data is based on it.
|
17
|
+
If you can't wait for libphonenumber to resolve the issue, try to use ```Phonelib.add_additional_regex``` and ```Phonelib.additional_regexes``` methods.
|
18
|
+
|
15
19
|
## Information
|
16
20
|
|
17
21
|
### Change Log
|
@@ -62,6 +66,18 @@ To disable sanitizing of passed phone number (keeping digits only)
|
|
62
66
|
Phonelib.strict_check = true
|
63
67
|
```
|
64
68
|
|
69
|
+
To change sanitized symbols on parsed number, so non-specified symbols won't be wiped and will fail the parsing
|
70
|
+
|
71
|
+
``` ruby
|
72
|
+
Phonelib.sanitize_regex = '[\.\-\(\) \;\+]'
|
73
|
+
```
|
74
|
+
|
75
|
+
To disable sanitizing of double prefix on passed phone number
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
Phonelib.strict_double_prefix_check = true
|
79
|
+
```
|
80
|
+
|
65
81
|
To set different extension separator on formatting, this setting doesn't affect parsing. Default setting is ';'
|
66
82
|
|
67
83
|
``` ruby
|
@@ -72,7 +88,7 @@ To set symbols that are used for separating extension from phone number for pars
|
|
72
88
|
|
73
89
|
``` ruby
|
74
90
|
Phonelib.extension_separate_symbols = '#;' # for single symbol separator
|
75
|
-
Phonelib.
|
91
|
+
Phonelib.extension_separate_symbols = %w(ext # ; extension) # each string will be treated as separator
|
76
92
|
```
|
77
93
|
|
78
94
|
In case you need to overwrite some Google's libphonenumber library data, you need to assign file path to this setter. File should be Marshal.dump'ed with existing structure like in ```Phonelib.phone_data```. Gem is simply doing ```merge``` between hashes.
|
@@ -81,6 +97,21 @@ In case you need to overwrite some Google's libphonenumber library data, you nee
|
|
81
97
|
Phonelib.override_phone_data = '/path/to/override_phone_data.dat'
|
82
98
|
```
|
83
99
|
|
100
|
+
In case you want to add some custom or still not updated regex patterns for certain type you can use additional regexes feature in a following way:
|
101
|
+
|
102
|
+
``` ruby
|
103
|
+
Phonelib.add_additional_regex :us, Phonelib::Core::MOBILE, '[5]{10}' # this will add number 1-555-555-5555 to be valid
|
104
|
+
Phonelib.add_additional_regex :gb, Phonelib::Core::MOBILE, '[1]{5}' # this will add number 44-11-111 to be valid
|
105
|
+
# you can also specify all regexes using this method
|
106
|
+
Phonelib.additional_regexes = [[:us, :mobile, "[5]{10}"], [:gb, :mobile, "[1]{5}"]]
|
107
|
+
# or just use dump method to keep them altogether
|
108
|
+
Phonelib.dump_additional_regexes # => [["US", :mobile, "[5]{10}"], ["GB", :mobile, "[1]{5}"]
|
109
|
+
```
|
110
|
+
|
111
|
+
(!) For a list of available types refer to this readme.
|
112
|
+
|
113
|
+
(!) Please note that regex should be added as string
|
114
|
+
|
84
115
|
In case phone number that was passed for parsing has "+" sign in the beginning, library will try to detect a country regarding the provided one.
|
85
116
|
|
86
117
|
### ActiveRecord Integration
|
@@ -109,7 +140,10 @@ Refer to [Google libphonenumber](http://code.google.com/p/libphonenumber/) for m
|
|
109
140
|
<tt>types: :mobile</tt> or <tt>types: [:voip, :mobile]</tt> - allows to validate against specific phone types patterns,
|
110
141
|
if mixed with <tt>possible</tt> will check if number is possible for specified type
|
111
142
|
|
112
|
-
<tt>
|
143
|
+
<tt>countries: :us</tt> or <tt>countries: [:us, :ca]</tt> - allows to validate against specific countries,
|
144
|
+
if mixed with <tt>possible</tt> will check if number is possible for specified countries
|
145
|
+
|
146
|
+
<tt>country_specifier: :method_name</tt> or <tt>country_specifier: -> instance { instance.country.try(:upcase) }</tt> - allows to specify country for validation dynamically for each validation. Usefull when phone is stored as national number without country prefix.
|
113
147
|
|
114
148
|
<tt>extensions: false</tt> - set to perform check for phone extension to be blank
|
115
149
|
|
@@ -143,6 +177,7 @@ Additionally you can run:
|
|
143
177
|
|
144
178
|
``` ruby
|
145
179
|
phone = Phonelib.parse('123456789')
|
180
|
+
phone = Phonelib.parse('+1 (972) 123-4567', 'US')
|
146
181
|
```
|
147
182
|
|
148
183
|
You can pass phone number with extension, it should be separated with <tt>;</tt> or <tt>#</tt> signs from the phone number.
|
@@ -222,7 +257,7 @@ phone.full_e164 # returns e164 phone representation with extension
|
|
222
257
|
phone.full_international # returns formatted international number with extension
|
223
258
|
```
|
224
259
|
|
225
|
-
You can pass <tt>false</tt> to <tt>national</tt> and <tt>international</tt> methods in order to get unformatted
|
260
|
+
You can pass <tt>false</tt> to <tt>national</tt> and <tt>international</tt> methods in order to get unformatted representations
|
226
261
|
|
227
262
|
``` ruby
|
228
263
|
phone.international(false) # returns unformatted international phone
|
@@ -235,12 +270,33 @@ You can get E164 formatted number
|
|
235
270
|
phone.e164 # returns number in E164 format
|
236
271
|
```
|
237
272
|
|
273
|
+
You can define prefix for ```international``` and ```e164``` related methods to get formatted number prefixed with anything you need.
|
274
|
+
|
275
|
+
``` ruby
|
276
|
+
phone.international('00') # returns formatted international number prefixed by 00 instead of +
|
277
|
+
phone.e164('00') # returns e164 represantation of a number prefixed by 00 instead of +
|
278
|
+
phone.full_international('00') # returns formatted international number with extension prefixed by 00 instead of +
|
279
|
+
phone.full_e164('00') # returns e164 represantation of a number with extension prefixed by 00 instead of +
|
280
|
+
phone.international_00 # same as phone.international('00'). 00 can be replaced with whatever you need
|
281
|
+
phone.e164_00 # same as phone.international('00')
|
282
|
+
```
|
283
|
+
|
238
284
|
There is a ```to_s``` method, it will return ```e164``` in case number is valid and ```original``` otherwise
|
239
285
|
|
240
286
|
``` ruby
|
241
287
|
phone.to_s # returns number in E164 format if number is valid or original otherwise
|
242
288
|
```
|
243
289
|
|
290
|
+
You can compare 2 instances of ```Phonelib::Phone``` with ```==``` method or just use it with string
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
phone1 = Phonelib.parse('+12125551234') # Phonelib::Phone instance
|
294
|
+
phone2 = Phonelib.parse('+12125551234') # Phonelib::Phone instance
|
295
|
+
phone1 == phone2 # returns true
|
296
|
+
phone1 == '+12125551234' # returns true
|
297
|
+
phone1 == '12125551234;123' # returns true
|
298
|
+
```
|
299
|
+
|
244
300
|
There is extended data available for numbers. It will return <tt>nil</tt> in case there is no data or phone is impossible.
|
245
301
|
Can return array of values in case there are some results for specified number
|
246
302
|
|
data/Rakefile
CHANGED
@@ -22,6 +22,13 @@ end
|
|
22
22
|
Bundler::GemHelper.install_tasks
|
23
23
|
|
24
24
|
require 'rspec/core/rake_task'
|
25
|
+
module TempFixForRakeLastComment
|
26
|
+
def last_comment
|
27
|
+
last_description
|
28
|
+
end
|
29
|
+
end
|
30
|
+
Rake::Application.send :include, TempFixForRakeLastComment
|
31
|
+
|
25
32
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
26
33
|
if defined? Rails
|
27
34
|
puts 'Rails found! Running tests with Rails'
|
data/data/extended_data.dat
CHANGED
Binary file
|
data/data/phone_data.dat
CHANGED
Binary file
|
data/lib/phonelib/core.rb
CHANGED
@@ -107,6 +107,38 @@ module Phonelib
|
|
107
107
|
@@strict_check = strict
|
108
108
|
end
|
109
109
|
|
110
|
+
# @private sanitizing regex, matching symbols will get removed from parsed number, must be string
|
111
|
+
@@sanitize_regex = '[^0-9]+'
|
112
|
+
|
113
|
+
# getter for sanitize regex
|
114
|
+
# @return [String] regex of symbols to wipe from parsed number
|
115
|
+
def sanitize_regex
|
116
|
+
@@sanitize_regex
|
117
|
+
end
|
118
|
+
|
119
|
+
# setter for sanitize regex
|
120
|
+
# @param regex [String] symbols to wipe from parsed number
|
121
|
+
# @return [String] regex of symbols to wipe from parsed number
|
122
|
+
def sanitize_regex=(regex)
|
123
|
+
@@sanitize_regex = regex.is_a?(String) ? regex : regex.to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
# @private strict double prefix check for validator, doesn't sanitize number
|
127
|
+
@@strict_double_prefix_check = false
|
128
|
+
|
129
|
+
# getter for strict double prefix check flag
|
130
|
+
# @return [Boolean] Flag defines whether to do strict double prefix parsing check
|
131
|
+
def strict_double_prefix_check
|
132
|
+
@@strict_double_prefix_check
|
133
|
+
end
|
134
|
+
|
135
|
+
# setter for strict double prefix check flag
|
136
|
+
# @param strict [Boolean] make a strict double prefix parsing or not
|
137
|
+
# @return [Boolean] Flag defines whether to do strict double prefix parsing check
|
138
|
+
def strict_double_prefix_check=(strict)
|
139
|
+
@@strict_double_prefix_check = strict
|
140
|
+
end
|
141
|
+
|
110
142
|
@@override_phone_data = nil
|
111
143
|
# setter for data file to use
|
112
144
|
def override_phone_data=(file_path)
|
@@ -117,6 +149,42 @@ module Phonelib
|
|
117
149
|
@@override_phone_data
|
118
150
|
end
|
119
151
|
|
152
|
+
@@additional_regexes = {}
|
153
|
+
# setter for data file to use
|
154
|
+
def additional_regexes=(data)
|
155
|
+
return unless data.is_a?(Array)
|
156
|
+
@@additional_regexes = {}
|
157
|
+
data.each do |row|
|
158
|
+
next if row.size != 3
|
159
|
+
add_additional_regex(*row)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_additional_regex(country, type, national_regex)
|
164
|
+
return unless Phonelib::Core::TYPES_DESC.keys.include?(type.to_sym)
|
165
|
+
return unless national_regex.is_a?(String)
|
166
|
+
@@phone_data = nil
|
167
|
+
@@additional_regexes[country.to_s.upcase] ||= {}
|
168
|
+
@@additional_regexes[country.to_s.upcase][type] ||= []
|
169
|
+
@@additional_regexes[country.to_s.upcase][type] << national_regex
|
170
|
+
end
|
171
|
+
|
172
|
+
def dump_additional_regexes
|
173
|
+
rows = []
|
174
|
+
@@additional_regexes.each do |country, types|
|
175
|
+
types.each do |type, regexes|
|
176
|
+
regexes.each do |regex|
|
177
|
+
rows << [country, type, regex]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
rows
|
182
|
+
end
|
183
|
+
|
184
|
+
def additional_regexes
|
185
|
+
@@additional_regexes
|
186
|
+
end
|
187
|
+
|
120
188
|
@@vanity_conversion = false
|
121
189
|
# setter for vanity phone numbers chars replacement
|
122
190
|
def vanity_conversion=(value)
|
@@ -285,6 +353,8 @@ module Phonelib
|
|
285
353
|
EXT_PREFIXES = :prefixes
|
286
354
|
# @private Extended data geo names array key
|
287
355
|
EXT_GEO_NAMES = :geo_names
|
356
|
+
# @private Extended data country names array key
|
357
|
+
EXT_COUNTRY_NAMES = :country_names
|
288
358
|
# @private Extended data timezones array key
|
289
359
|
EXT_TIMEZONES = :timezones
|
290
360
|
# @private Extended data carriers array key
|
@@ -359,6 +429,21 @@ module Phonelib
|
|
359
429
|
override_data_file = Marshal.load(File.binread(override_phone_data))
|
360
430
|
default_data.merge!(override_data_file)
|
361
431
|
end
|
432
|
+
additional_regexes.each do |country, types|
|
433
|
+
types.each do |type, regex|
|
434
|
+
default_data[country][Core::TYPES][type] ||= {}
|
435
|
+
[Core::VALID_PATTERN, Core::POSSIBLE_PATTERN].each do |key|
|
436
|
+
if default_data[country][Core::TYPES][type][key]
|
437
|
+
default_data[country][Core::TYPES][type][key] << "|#{regex.join('|')}"
|
438
|
+
else
|
439
|
+
default_data[country][Core::TYPES][type][key] = regex.join('|')
|
440
|
+
end
|
441
|
+
if type != Core::GENERAL
|
442
|
+
default_data[country][Core::TYPES][Core::GENERAL][key] << "|#{regex.join('|')}"
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
362
447
|
default_data
|
363
448
|
end
|
364
449
|
|
@@ -18,7 +18,48 @@ module Phonelib
|
|
18
18
|
include Phonelib::DataImporterHelper
|
19
19
|
|
20
20
|
# countries that can have double country prefix in number
|
21
|
-
DOUBLE_COUNTRY_CODES_COUNTRIES = %w(IN DE BR IT NO)
|
21
|
+
DOUBLE_COUNTRY_CODES_COUNTRIES = %w(IN DE BR IT NO PL CU VN)
|
22
|
+
FORMAT_SHARING = {
|
23
|
+
'CA' => 'US',
|
24
|
+
'CC' => 'AU',
|
25
|
+
'CX' => 'AU',
|
26
|
+
'DM' => 'US',
|
27
|
+
'DO' => 'US',
|
28
|
+
'EH' => 'MA',
|
29
|
+
'GD' => 'US',
|
30
|
+
'GG' => 'GB',
|
31
|
+
'GU' => 'US',
|
32
|
+
'IM' => 'GB',
|
33
|
+
'JE' => 'GB',
|
34
|
+
'JM' => 'US',
|
35
|
+
'KN' => 'US',
|
36
|
+
'KY' => 'US',
|
37
|
+
'KZ' => 'RU',
|
38
|
+
'LC' => 'US',
|
39
|
+
'MF' => 'GP',
|
40
|
+
'MP' => 'US',
|
41
|
+
'MS' => 'US',
|
42
|
+
'PR' => 'US',
|
43
|
+
'SJ' => 'NO',
|
44
|
+
'SX' => 'US',
|
45
|
+
'TA' => 'SH',
|
46
|
+
'TC' => 'US',
|
47
|
+
'TT' => 'US',
|
48
|
+
'VA' => 'IT',
|
49
|
+
'VC' => 'US',
|
50
|
+
'VG' => 'US',
|
51
|
+
'VI' => 'US',
|
52
|
+
'YT' => 'RE',
|
53
|
+
'AG' => 'US',
|
54
|
+
'AI' => 'US',
|
55
|
+
'AS' => 'US',
|
56
|
+
'AX' => 'FI',
|
57
|
+
'BB' => 'US',
|
58
|
+
'BL' => 'GP',
|
59
|
+
'BM' => 'US',
|
60
|
+
'BQ' => 'CW',
|
61
|
+
'BS' => 'US',
|
62
|
+
}
|
22
63
|
|
23
64
|
# main data file in repo
|
24
65
|
MAIN_FILE = 'resources/PhoneNumberMetadata.xml'
|
@@ -42,6 +83,7 @@ module Phonelib
|
|
42
83
|
@geo_names = []
|
43
84
|
@timezones = []
|
44
85
|
@carriers = []
|
86
|
+
@countries = {}
|
45
87
|
|
46
88
|
run_import
|
47
89
|
end
|
@@ -54,9 +96,11 @@ module Phonelib
|
|
54
96
|
import_main_data
|
55
97
|
import_short_data
|
56
98
|
import_alternate_formats
|
99
|
+
process_format_links
|
57
100
|
import_geocoding_data
|
58
101
|
import_timezone_data
|
59
102
|
import_carrier_data
|
103
|
+
import_country_names
|
60
104
|
save_data_file
|
61
105
|
save_extended_data_file
|
62
106
|
end
|
@@ -113,6 +157,14 @@ module Phonelib
|
|
113
157
|
end
|
114
158
|
end
|
115
159
|
|
160
|
+
# some countries missing formats, and are linking them to another countries
|
161
|
+
def process_format_links
|
162
|
+
FORMAT_SHARING.each do |destination, source|
|
163
|
+
@data[destination][:formats] ||= []
|
164
|
+
@data[destination][:formats] = @data[destination][:formats] + @data[source][:formats]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
116
168
|
# method parses geocoding data dir
|
117
169
|
def import_geocoding_data
|
118
170
|
puts 'IMPORTING GEOCODING DATA'
|
@@ -137,6 +189,21 @@ module Phonelib
|
|
137
189
|
:c)
|
138
190
|
end
|
139
191
|
|
192
|
+
# import country names
|
193
|
+
def import_country_names
|
194
|
+
puts 'IMPORTING COUNTRY NAMES'
|
195
|
+
|
196
|
+
require 'open-uri'
|
197
|
+
require 'csv'
|
198
|
+
io = open('http://api.geonames.org/countryInfoCSV?username=demo&style=full')
|
199
|
+
csv = CSV.new(io, {col_sep: "\t"})
|
200
|
+
csv.each do |row|
|
201
|
+
next if row[0].nil? || row[0].start_with?('#') || row[0].empty? || row[0].size != 2
|
202
|
+
|
203
|
+
@countries[row[0]] = row[4]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
140
207
|
# adds double country code flag in case country allows
|
141
208
|
def add_double_country_flag(country)
|
142
209
|
if DOUBLE_COUNTRY_CODES_COUNTRIES.include?(country[:id])
|
@@ -22,6 +22,7 @@ module Phonelib
|
|
22
22
|
extended = {
|
23
23
|
Phonelib::Core::EXT_PREFIXES => @prefixes,
|
24
24
|
Phonelib::Core::EXT_GEO_NAMES => @geo_names,
|
25
|
+
Phonelib::Core::EXT_COUNTRY_NAMES => @countries,
|
25
26
|
Phonelib::Core::EXT_TIMEZONES => @timezones,
|
26
27
|
Phonelib::Core::EXT_CARRIERS => @carriers
|
27
28
|
}
|
data/lib/phonelib/phone.rb
CHANGED
@@ -7,6 +7,9 @@ module Phonelib
|
|
7
7
|
# @!attribute [r] extension
|
8
8
|
# @return [String] phone extension passed for parsing after a number
|
9
9
|
attr_reader :extension
|
10
|
+
# @!attribute [r] national_number
|
11
|
+
# @return [String] phone national number
|
12
|
+
attr_reader :national_number
|
10
13
|
|
11
14
|
# including module that has all phone analyzing methods
|
12
15
|
include Phonelib::PhoneAnalyzer
|
@@ -37,12 +40,21 @@ module Phonelib
|
|
37
40
|
valid? ? e164 : original
|
38
41
|
end
|
39
42
|
|
43
|
+
# Compare a phone number against a string or other parsed number
|
44
|
+
# @param other [String|Phonelib::Phone] Phone number to compare against
|
45
|
+
# @return [Boolean] result of equality comparison
|
46
|
+
def ==(other)
|
47
|
+
other = Phonelib.parse(other) unless other.is_a?(Phonelib::Phone)
|
48
|
+
return (e164 == other.e164) if valid? && other.valid?
|
49
|
+
original == other.original
|
50
|
+
end
|
51
|
+
|
40
52
|
# method to get sanitized phone number (only numbers)
|
41
53
|
# @return [String] Sanitized phone number
|
42
54
|
def sanitized
|
43
55
|
@sanitized ||=
|
44
56
|
vanity_converted(@original).gsub(
|
45
|
-
Phonelib.strict_check ? cr('^\+') : cr(
|
57
|
+
Phonelib.strict_check ? cr('^\+') : cr(Phonelib.sanitize_regex),
|
46
58
|
'')
|
47
59
|
end
|
48
60
|
|
@@ -16,15 +16,38 @@ module Phonelib
|
|
16
16
|
# * +passed_country+ - Country provided for parsing. Must be ISO code of
|
17
17
|
# country (2 letters) like 'US', 'us' or :us for United States
|
18
18
|
def analyze(phone, passed_country)
|
19
|
-
|
19
|
+
countries = country_or_default_country passed_country
|
20
20
|
|
21
|
+
return analyze_single_country(phone, countries.first, passed_country) if countries.size == 1
|
22
|
+
|
23
|
+
results = {}
|
24
|
+
countries.map do |country|
|
25
|
+
results.merge! analyze_single_country(phone, country, passed_country)
|
26
|
+
end
|
27
|
+
|
28
|
+
pick_results(results)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# pick best result when several countries specified
|
34
|
+
def pick_results(results)
|
35
|
+
[:valid, :possible].each do |key|
|
36
|
+
final = results.select { |_k, v| v[key].any? }
|
37
|
+
return decorate_analyze_result(final) if final.size > 0
|
38
|
+
end
|
39
|
+
|
40
|
+
decorate_analyze_result(results)
|
41
|
+
end
|
42
|
+
|
43
|
+
def analyze_single_country(phone, country, passed_country)
|
21
44
|
result = parse_country(phone, country)
|
22
45
|
d_result = case
|
23
46
|
when result && result.values.find { |e| e[:valid].any? }
|
24
47
|
# all is good, return result
|
25
48
|
when passed_country.nil?
|
26
49
|
# trying for all countries if no country was passed
|
27
|
-
detect_and_parse
|
50
|
+
detect_and_parse(phone, country)
|
28
51
|
when country_can_dp?(country)
|
29
52
|
# if country allows double prefix trying modified phone
|
30
53
|
parse_country(changed_dp_phone(country, phone), country)
|
@@ -32,8 +55,6 @@ module Phonelib
|
|
32
55
|
better_result(result, d_result)
|
33
56
|
end
|
34
57
|
|
35
|
-
private
|
36
|
-
|
37
58
|
# method checks which result is better to return
|
38
59
|
def better_result(base_result, result = nil)
|
39
60
|
base_result ||= {}
|
@@ -102,11 +123,11 @@ module Phonelib
|
|
102
123
|
# ==== Attributes
|
103
124
|
#
|
104
125
|
# * +phone+ - phone number for parsing
|
105
|
-
def detect_and_parse(phone)
|
126
|
+
def detect_and_parse(phone, country)
|
106
127
|
result = {}
|
107
128
|
Phonelib.phone_data.each do |key, data|
|
108
129
|
parsed = parse_single_country(phone, data)
|
109
|
-
if double_prefix_allowed?(data, phone, parsed && parsed[key])
|
130
|
+
if (!Phonelib.strict_double_prefix_check || key == country) && double_prefix_allowed?(data, phone, parsed && parsed[key])
|
110
131
|
parsed = parse_single_country(changed_dp_phone(key, phone), data)
|
111
132
|
end
|
112
133
|
result.merge!(parsed) unless parsed.nil?
|
@@ -3,6 +3,14 @@ module Phonelib
|
|
3
3
|
module PhoneAnalyzerHelper
|
4
4
|
private
|
5
5
|
|
6
|
+
def decorate_analyze_result(result)
|
7
|
+
if result.size == 1
|
8
|
+
result
|
9
|
+
else
|
10
|
+
Hash[result.take(1)]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
6
14
|
def original_starts_with_plus?
|
7
15
|
original_s[0] == Core::PLUS_SIGN
|
8
16
|
end
|
@@ -90,7 +98,11 @@ module Phonelib
|
|
90
98
|
# * +country+ - country passed for parsing
|
91
99
|
def country_or_default_country(country)
|
92
100
|
country ||= (original_starts_with_plus? ? nil : Phonelib.default_country)
|
93
|
-
|
101
|
+
if country.is_a?(Array)
|
102
|
+
country.compact.map { |e| e.to_s.upcase }
|
103
|
+
else
|
104
|
+
[country && country.to_s.upcase]
|
105
|
+
end
|
94
106
|
end
|
95
107
|
|
96
108
|
# constructs full regex for phone validation for provided phone data
|
@@ -102,6 +114,7 @@ module Phonelib
|
|
102
114
|
# * +country_optional+ - whether to put country code as optional group
|
103
115
|
def full_regex_for_data(data, type, country_optional = true)
|
104
116
|
regex = []
|
117
|
+
regex << '0{2}?'
|
105
118
|
regex << "(#{data[Core::INTERNATIONAL_PREFIX]})?"
|
106
119
|
regex << "(#{data[Core::COUNTRY_CODE]})#{country_optional ? '?' : ''}"
|
107
120
|
regex << "(#{data[Core::NATIONAL_PREFIX_FOR_PARSING] || data[Core::NATIONAL_PREFIX]})?"
|
@@ -133,7 +146,7 @@ module Phonelib
|
|
133
146
|
def phone_match_data?(phone, data, possible = false)
|
134
147
|
country_code = "#{data[Core::COUNTRY_CODE]}"
|
135
148
|
inter_prefix = "(#{data[Core::INTERNATIONAL_PREFIX]})?"
|
136
|
-
return unless phone.match cr("
|
149
|
+
return unless phone.match cr("^0{2}?#{inter_prefix}#{country_code}")
|
137
150
|
|
138
151
|
type = possible ? Core::POSSIBLE_PATTERN : Core::VALID_PATTERN
|
139
152
|
phone.match full_regex_for_data(data, type, false)
|
@@ -32,6 +32,13 @@ module Phonelib
|
|
32
32
|
Phonelib::Core::EXT_CARRIER_KEY
|
33
33
|
end
|
34
34
|
|
35
|
+
# returns valid country name
|
36
|
+
def valid_country_name
|
37
|
+
return unless valid?
|
38
|
+
|
39
|
+
Phonelib.phone_ext_data[Phonelib::Core::EXT_COUNTRY_NAMES][valid_country]
|
40
|
+
end
|
41
|
+
|
35
42
|
private
|
36
43
|
|
37
44
|
# @private get name from extended phone data by keys
|
@@ -42,7 +49,7 @@ module Phonelib
|
|
42
49
|
# * +id_key+ - parameter id key in resolved extended data for number
|
43
50
|
#
|
44
51
|
def get_ext_name(names_key, id_key)
|
45
|
-
return nil unless ext_data[id_key]
|
52
|
+
return nil unless ext_data[id_key]
|
46
53
|
|
47
54
|
res = Phonelib.phone_ext_data[names_key][ext_data[id_key]]
|
48
55
|
return nil unless res
|
@@ -51,7 +58,7 @@ module Phonelib
|
|
51
58
|
|
52
59
|
# @private returns extended data ids for current number
|
53
60
|
def ext_data
|
54
|
-
return @ext_data if @ext_data
|
61
|
+
return @ext_data if defined?(@ext_data) && @ext_data
|
55
62
|
|
56
63
|
result = default_ext_data
|
57
64
|
return result unless possible?
|
@@ -72,7 +79,7 @@ module Phonelib
|
|
72
79
|
# @private default extended data
|
73
80
|
def default_ext_data
|
74
81
|
result = {}
|
75
|
-
EXT_KEYS.each { |key| result[key] =
|
82
|
+
EXT_KEYS.each { |key| result[key] = nil }
|
76
83
|
result
|
77
84
|
end
|
78
85
|
end
|
@@ -36,22 +36,24 @@ module Phonelib
|
|
36
36
|
Phonelib.phone_data[country][Core::COUNTRY_CODE]
|
37
37
|
end
|
38
38
|
|
39
|
-
# Returns e164 formatted phone number
|
39
|
+
# Returns e164 formatted phone number. Method can receive single string parameter that will be defined as prefix
|
40
40
|
# @param formatted [Boolean] whether to return numbers only or formatted
|
41
|
+
# @param prefix [String] prefix to be placed before the number, "+" by default
|
41
42
|
# @return [String] formatted international number
|
42
|
-
def international(formatted = true)
|
43
|
+
def international(formatted = true, prefix = '+')
|
44
|
+
prefix = formatted if formatted.is_a?(String)
|
43
45
|
return nil if sanitized.empty?
|
44
|
-
return "
|
45
|
-
return country_code
|
46
|
+
return "#{prefix}#{country_prefix_or_not}#{sanitized}" unless valid?
|
47
|
+
return "#{prefix}#{country_code}#{@national_number}" unless formatted
|
46
48
|
|
47
49
|
fmt = @data[country][:format]
|
48
50
|
national = @national_number
|
49
51
|
if (matches = @national_number.match(cr(fmt[Core::PATTERN])))
|
50
52
|
fmt = fmt[:intl_format] || fmt[:format]
|
51
|
-
national = fmt.gsub(/\$\d/) { |el| matches[el[1].to_i] }
|
53
|
+
national = fmt.gsub(/\$\d/) { |el| matches[el[1].to_i] } unless fmt == 'NA'
|
52
54
|
end
|
53
55
|
|
54
|
-
"
|
56
|
+
"#{prefix}#{country_code} #{national}"
|
55
57
|
end
|
56
58
|
|
57
59
|
# returns national formatted number with extension added
|
@@ -61,22 +63,25 @@ module Phonelib
|
|
61
63
|
end
|
62
64
|
|
63
65
|
# returns international formatted number with extension added
|
66
|
+
# @param prefix [String] prefix to be placed before the number, "+" by default
|
64
67
|
# @return [String] formatted internation phone number with extension
|
65
|
-
def full_international
|
66
|
-
"#{international}#{formatted_extension}"
|
68
|
+
def full_international(prefix = '+')
|
69
|
+
"#{international(true, prefix)}#{formatted_extension}"
|
67
70
|
end
|
68
71
|
|
69
72
|
# returns e164 format of phone with extension added
|
73
|
+
# @param prefix [String] prefix to be placed before the number, "+" by default
|
70
74
|
# @return [String] phone formatted in E164 format with extension
|
71
|
-
def full_e164
|
72
|
-
"#{e164}#{formatted_extension}"
|
75
|
+
def full_e164(prefix = '+')
|
76
|
+
"#{e164(prefix)}#{formatted_extension}"
|
73
77
|
end
|
74
78
|
|
75
79
|
# Returns e164 unformatted phone number
|
80
|
+
# @param prefix [String] prefix to be placed before the number, "+" by default
|
76
81
|
# @return [String] phone formatted in E164 format
|
77
|
-
def e164
|
78
|
-
international = self.international
|
79
|
-
international && international
|
82
|
+
def e164(prefix = '+')
|
83
|
+
international = self.international(false, '')
|
84
|
+
international && "#{prefix}#{international}"
|
80
85
|
end
|
81
86
|
|
82
87
|
# returns area code of parsed number
|
@@ -93,6 +98,15 @@ module Phonelib
|
|
93
98
|
format_match[take_group]
|
94
99
|
end
|
95
100
|
|
101
|
+
def method_missing(method, *args)
|
102
|
+
prefix_methods = %w(international_ full_international_ e164_ full_e164_)
|
103
|
+
method_s = method.to_s
|
104
|
+
prefix_methods.each do |key|
|
105
|
+
return send(key[0..-2], method_s.gsub(key, '')) if method_s.start_with?(key)
|
106
|
+
end
|
107
|
+
super
|
108
|
+
end
|
109
|
+
|
96
110
|
private
|
97
111
|
|
98
112
|
# @private defines if phone can have area code
|
@@ -135,7 +149,12 @@ module Phonelib
|
|
135
149
|
rule.gsub!(/(\$NP|\$FG)/, '$NP' => prefix, '$FG' => '$1')
|
136
150
|
|
137
151
|
# add space to format groups, change first group to rule,
|
138
|
-
format_string = format[:format].gsub(/(\d)\$/, '\\1 $')
|
152
|
+
format_string = format[:format].gsub(/(\d)\$/, '\\1 $')
|
153
|
+
if format_string.include? '$1'
|
154
|
+
format_string.gsub! '$1', rule
|
155
|
+
else
|
156
|
+
format_string = rule.gsub('$1', '') + format_string
|
157
|
+
end
|
139
158
|
|
140
159
|
@formatting_data =
|
141
160
|
[@national_number.match(/#{format[Core::PATTERN]}/), format_string]
|
data/lib/phonelib/version.rb
CHANGED
data/lib/phonelib.rb
CHANGED
@@ -12,5 +12,9 @@ module Phonelib
|
|
12
12
|
end
|
13
13
|
|
14
14
|
if defined?(ActiveModel) || defined?(Rails)
|
15
|
-
|
15
|
+
if RUBY_VERSION >= '3.0.0'
|
16
|
+
autoload :PhoneValidator, 'validators/phone_validator3'
|
17
|
+
else
|
18
|
+
autoload :PhoneValidator, 'validators/phone_validator'
|
19
|
+
end
|
16
20
|
end
|
@@ -36,6 +36,13 @@
|
|
36
36
|
# validates :mobile, phone: { possible: true, types: :mobile }
|
37
37
|
# end
|
38
38
|
#
|
39
|
+
# validates that phone is valid and it is from specified country or countries
|
40
|
+
#
|
41
|
+
# class Phone < ActiveRecord::Base
|
42
|
+
# attr_accessible :number
|
43
|
+
# validates :number, phone: { countries: [:us, :ca] }
|
44
|
+
# end
|
45
|
+
#
|
39
46
|
# Validates that attribute does not include an extension.
|
40
47
|
# The default setting is to allow extensions
|
41
48
|
#
|
@@ -51,21 +58,11 @@ class PhoneValidator < ActiveModel::EachValidator
|
|
51
58
|
# Validation method
|
52
59
|
def validate_each(record, attribute, value)
|
53
60
|
return if options[:allow_blank] && value.blank?
|
54
|
-
allowed_extensions = options.has_key?(:extensions) ? options[:extensions] : true
|
55
61
|
|
56
|
-
phone = parse(value, specified_country(record))
|
57
|
-
valid =
|
58
|
-
phone.send(validate_method)
|
59
|
-
else
|
60
|
-
(phone_types(phone) & types).size > 0
|
61
|
-
end
|
62
|
+
@phone = parse(value, specified_country(record))
|
63
|
+
valid = phone_valid? && valid_types? && valid_country? && valid_extensions?
|
62
64
|
|
63
|
-
|
64
|
-
if valid && !allowed_extensions && !phone.extension.empty?
|
65
|
-
valid = false
|
66
|
-
end
|
67
|
-
|
68
|
-
record.errors.add(attribute, message, options) unless valid
|
65
|
+
record.errors.add(attribute, message, **options) unless valid
|
69
66
|
end
|
70
67
|
|
71
68
|
private
|
@@ -74,34 +71,60 @@ class PhoneValidator < ActiveModel::EachValidator
|
|
74
71
|
options[:message] || :invalid
|
75
72
|
end
|
76
73
|
|
77
|
-
def
|
78
|
-
options[:possible] ? :possible? : :valid?
|
74
|
+
def phone_valid?
|
75
|
+
@phone.send(options[:possible] ? :possible? : :valid?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def valid_types?
|
79
|
+
return true unless options[:types]
|
80
|
+
(phone_types & types).size > 0
|
81
|
+
end
|
82
|
+
|
83
|
+
def valid_country?
|
84
|
+
return true unless options[:countries]
|
85
|
+
(phone_countries & countries).size > 0
|
86
|
+
end
|
87
|
+
|
88
|
+
def valid_extensions?
|
89
|
+
return true if !options.has_key?(:extensions) || options[:extensions]
|
90
|
+
@phone.extension.empty?
|
79
91
|
end
|
80
92
|
|
81
93
|
def specified_country(record)
|
82
94
|
return unless options[:country_specifier]
|
83
|
-
options[:country_specifier].call(record)
|
84
|
-
end
|
85
95
|
|
86
|
-
|
87
|
-
|
88
|
-
|
96
|
+
if options[:country_specifier].is_a?(Symbol)
|
97
|
+
record.send(options[:country_specifier])
|
98
|
+
else
|
99
|
+
options[:country_specifier].call(record)
|
100
|
+
end
|
89
101
|
end
|
90
102
|
|
91
103
|
# @private
|
92
|
-
|
93
|
-
def phone_types(phone)
|
104
|
+
def phone_types
|
94
105
|
method = options[:possible] ? :possible_types : :types
|
95
|
-
phone_types = phone.send(method)
|
106
|
+
phone_types = @phone.send(method)
|
96
107
|
if (phone_types & [Phonelib::Core::FIXED_OR_MOBILE]).size > 0
|
97
108
|
phone_types += [Phonelib::Core::FIXED_LINE, Phonelib::Core::MOBILE]
|
98
109
|
end
|
99
110
|
phone_types
|
100
111
|
end
|
101
112
|
|
113
|
+
# @private
|
114
|
+
def phone_countries
|
115
|
+
method = options[:possible] ? :countries : :valid_countries
|
116
|
+
@phone.send(method)
|
117
|
+
end
|
118
|
+
|
102
119
|
# @private
|
103
120
|
def types
|
104
121
|
types = options[:types].is_a?(Array) ? options[:types] : [options[:types]]
|
105
122
|
types.map(&:to_sym)
|
106
123
|
end
|
124
|
+
|
125
|
+
# @private
|
126
|
+
def countries
|
127
|
+
countries = options[:countries].is_a?(Array) ? options[:countries] : [options[:countries]]
|
128
|
+
countries.map { |c| c.to_s.upcase }
|
129
|
+
end
|
107
130
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# Validator class for phone validations
|
2
|
+
#
|
3
|
+
# ==== Examples
|
4
|
+
#
|
5
|
+
# Validates that attribute is a valid phone number.
|
6
|
+
# If empty value passed for attribute it fails.
|
7
|
+
#
|
8
|
+
# class Phone < ActiveRecord::Base
|
9
|
+
# attr_accessible :number
|
10
|
+
# validates :number, phone: true
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Validates that attribute is a possible phone number.
|
14
|
+
# If empty value passed for attribute it fails.
|
15
|
+
#
|
16
|
+
# class Phone < ActiveRecord::Base
|
17
|
+
# attr_accessible :number
|
18
|
+
# validates :number, phone: { possible: true }
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Validates that attribute is a valid phone number.
|
22
|
+
# Empty value is allowed to be passed.
|
23
|
+
#
|
24
|
+
# class Phone < ActiveRecord::Base
|
25
|
+
# attr_accessible :number
|
26
|
+
# validates :number, phone: { allow_blank: true }
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# Validates that attribute is a valid phone number of specified type(s).
|
30
|
+
# It is also possible to check that attribute is a possible number of specified
|
31
|
+
# type(s). Symbol or array accepted.
|
32
|
+
#
|
33
|
+
# class Phone < ActiveRecord::Base
|
34
|
+
# attr_accessible :number, :mobile
|
35
|
+
# validates :number, phone: { types: [:mobile, :fixed], allow_blank: true }
|
36
|
+
# validates :mobile, phone: { possible: true, types: :mobile }
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# validates that phone is valid and it is from specified country or countries
|
40
|
+
#
|
41
|
+
# class Phone < ActiveRecord::Base
|
42
|
+
# attr_accessible :number
|
43
|
+
# validates :number, phone: { countries: [:us, :ca] }
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# Validates that attribute does not include an extension.
|
47
|
+
# The default setting is to allow extensions
|
48
|
+
#
|
49
|
+
# class Phone < ActiveRecord::Base
|
50
|
+
# attr_accessible :number
|
51
|
+
# validates :number, phone: { extensions: false }
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
class PhoneValidator < ActiveModel::EachValidator
|
55
|
+
# Include all core methods
|
56
|
+
include Phonelib::Core
|
57
|
+
|
58
|
+
# Validation method
|
59
|
+
def validate_each(record, attribute, value)
|
60
|
+
return if options[:allow_blank] && value.blank?
|
61
|
+
|
62
|
+
@phone = parse(value, specified_country(record))
|
63
|
+
valid = phone_valid? && valid_types? && valid_country? && valid_extensions?
|
64
|
+
|
65
|
+
record.errors.add(attribute, message, **options) unless valid
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def message
|
71
|
+
options[:message] || :invalid
|
72
|
+
end
|
73
|
+
|
74
|
+
def phone_valid?
|
75
|
+
@phone.send(options[:possible] ? :possible? : :valid?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def valid_types?
|
79
|
+
return true unless options[:types]
|
80
|
+
(phone_types & types).size > 0
|
81
|
+
end
|
82
|
+
|
83
|
+
def valid_country?
|
84
|
+
return true unless options[:countries]
|
85
|
+
(phone_countries & countries).size > 0
|
86
|
+
end
|
87
|
+
|
88
|
+
def valid_extensions?
|
89
|
+
return true if !options.has_key?(:extensions) || options[:extensions]
|
90
|
+
@phone.extension.empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
def specified_country(record)
|
94
|
+
return unless options[:country_specifier]
|
95
|
+
|
96
|
+
if options[:country_specifier].is_a?(Symbol)
|
97
|
+
record.send(options[:country_specifier])
|
98
|
+
else
|
99
|
+
options[:country_specifier].call(record)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# @private
|
104
|
+
def phone_types
|
105
|
+
method = options[:possible] ? :possible_types : :types
|
106
|
+
phone_types = @phone.send(method)
|
107
|
+
if (phone_types & [Phonelib::Core::FIXED_OR_MOBILE]).size > 0
|
108
|
+
phone_types += [Phonelib::Core::FIXED_LINE, Phonelib::Core::MOBILE]
|
109
|
+
end
|
110
|
+
phone_types
|
111
|
+
end
|
112
|
+
|
113
|
+
# @private
|
114
|
+
def phone_countries
|
115
|
+
method = options[:possible] ? :countries : :valid_countries
|
116
|
+
@phone.send(method)
|
117
|
+
end
|
118
|
+
|
119
|
+
# @private
|
120
|
+
def types
|
121
|
+
types = options[:types].is_a?(Array) ? options[:types] : [options[:types]]
|
122
|
+
types.map(&:to_sym)
|
123
|
+
end
|
124
|
+
|
125
|
+
# @private
|
126
|
+
def countries
|
127
|
+
countries = options[:countries].is_a?(Array) ? options[:countries] : [options[:countries]]
|
128
|
+
countries.map { |c| c.to_s.upcase }
|
129
|
+
end
|
130
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phonelib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vadim Senderovich
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "<"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '14.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "<"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '14.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: nokogiri
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.13.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
40
|
+
version: 1.13.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: pry
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 2.3.1
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - '='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 2.3.1
|
125
125
|
description: |2
|
126
126
|
Google libphonenumber library was taken as a basis for
|
127
127
|
this gem. Gem uses its data file for validations and number formatting.
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- lib/phonelib/version.rb
|
149
149
|
- lib/tasks/phonelib_tasks.rake
|
150
150
|
- lib/validators/phone_validator.rb
|
151
|
+
- lib/validators/phone_validator3.rb
|
151
152
|
homepage: https://github.com/daddyz/phonelib
|
152
153
|
licenses:
|
153
154
|
- MIT
|
@@ -168,8 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
169
|
- !ruby/object:Gem::Version
|
169
170
|
version: '0'
|
170
171
|
requirements: []
|
171
|
-
|
172
|
-
rubygems_version: 2.6.11
|
172
|
+
rubygems_version: 3.0.8
|
173
173
|
signing_key:
|
174
174
|
specification_version: 4
|
175
175
|
summary: Gem validates phone numbers with Google libphonenumber database
|