phonelib 0.6.55 → 0.8.2
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 +4 -4
- data/README.md +15 -3
- data/data/extended_data.dat +0 -0
- data/data/phone_data.dat +0 -0
- data/lib/phonelib/core.rb +30 -4
- data/lib/phonelib/data_importer.rb +52 -0
- data/lib/phonelib/phone.rb +2 -0
- data/lib/phonelib/phone_analyzer.rb +35 -7
- data/lib/phonelib/phone_analyzer_helper.rb +18 -3
- data/lib/phonelib/phone_formatter.rb +21 -8
- data/lib/phonelib/version.rb +1 -1
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba0b6be5c2a7713ded6c8bbc68a5d12d022b75cbc495bbdcd13cace46ee8467a
|
4
|
+
data.tar.gz: 6ad47b7928886d2c3222e072a2b2e73566baffe8462fa6a8ee353b9ff7630bca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a9dd8cc0c6b18a192575c169ff213e2bcf762d1a93f4ecc07aad89729a3173e03fe31e86e35ed4e583446410933367ef7ae9a6f365b47a55e75dd1c53b0b521
|
7
|
+
data.tar.gz: a468f6781963b983e54e367a0ddb99525ae2f5c1da8ca9b04829c248bf2ffe85705c9f96088eb09a39250cbb616d507288c84e54a27dee11cf42c4bd533dcb7f
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
[](https://www.jetbrains.com/ruby/)
|
4
4
|
[](http://badge.fury.io/rb/phonelib)
|
5
|
-
[](https://dl.circleci.com/status-badge/redirect/gh/daddyz/phonelib/tree/master)
|
6
6
|
[](https://codeclimate.com/github/daddyz/phonelib/coverage)
|
7
7
|
[](https://codeclimate.com/github/daddyz/phonelib)
|
8
8
|
[](http://inch-ci.org/github/daddyz/phonelib)
|
@@ -11,6 +11,11 @@ Phonelib is a gem allowing you to validate phone number. All validations are bas
|
|
11
11
|
Currently it can make basic validations and formatting to e164 international number format and national number format with prefix.
|
12
12
|
But it still doesn't include all Google's library functionality.
|
13
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
|
+
|
14
19
|
## Information
|
15
20
|
|
16
21
|
### Change Log
|
@@ -37,10 +42,11 @@ gem 'phonelib'
|
|
37
42
|
|
38
43
|
Run the bundle command to install it.
|
39
44
|
|
40
|
-
To set the default country (country names are [ISO 3166-1 Alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) codes), create a initializer in <tt>config/initializers/phonelib.rb</tt>:
|
45
|
+
To set the default country or several default countries for parsing (country names are [ISO 3166-1 Alpha-2](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) codes), create a initializer in <tt>config/initializers/phonelib.rb</tt>:
|
41
46
|
|
42
47
|
``` ruby
|
43
48
|
Phonelib.default_country = "CN"
|
49
|
+
Phonelib.default_country = ['CN', 'FR']
|
44
50
|
```
|
45
51
|
|
46
52
|
To use the ability to parse special numbers (Short Codes, Emergency etc.) you can set ```Phonelib.parse_special```. This is disabled by default
|
@@ -61,6 +67,12 @@ To disable sanitizing of passed phone number (keeping digits only)
|
|
61
67
|
Phonelib.strict_check = true
|
62
68
|
```
|
63
69
|
|
70
|
+
To disable country reset during parsing in case phone starts with + sign and country specified but country phone prefix doesn't match phone's prefix
|
71
|
+
|
72
|
+
``` ruby
|
73
|
+
Phonelib.ignore_plus = true
|
74
|
+
```
|
75
|
+
|
64
76
|
To change sanitized symbols on parsed number, so non-specified symbols won't be wiped and will fail the parsing
|
65
77
|
|
66
78
|
``` ruby
|
@@ -252,7 +264,7 @@ phone.full_e164 # returns e164 phone representation with extension
|
|
252
264
|
phone.full_international # returns formatted international number with extension
|
253
265
|
```
|
254
266
|
|
255
|
-
You can pass <tt>false</tt> to <tt>national</tt> and <tt>international</tt> methods in order to get unformatted
|
267
|
+
You can pass <tt>false</tt> to <tt>national</tt> and <tt>international</tt> methods in order to get unformatted representations
|
256
268
|
|
257
269
|
``` ruby
|
258
270
|
phone.international(false) # returns unformatted international phone
|
data/data/extended_data.dat
CHANGED
Binary file
|
data/data/phone_data.dat
CHANGED
Binary file
|
data/lib/phonelib/core.rb
CHANGED
@@ -10,6 +10,16 @@ module Phonelib
|
|
10
10
|
@@phone_data ||= load_data.freeze
|
11
11
|
end
|
12
12
|
|
13
|
+
# @private getter for phone data indexed by country code (internal use only)
|
14
|
+
def data_by_country_codes
|
15
|
+
@@data_by_country_codes ||= phone_data.each_value.group_by { |d| d[COUNTRY_CODE] }.freeze
|
16
|
+
end
|
17
|
+
|
18
|
+
# @private getter for all international prefixes in phone_data
|
19
|
+
def phone_data_int_prefixes
|
20
|
+
@@all_int_prefixes ||= phone_data.map {|k,v| v[:international_prefix] }.select { |v| v != '' }.compact.uniq.join('|').freeze
|
21
|
+
end
|
22
|
+
|
13
23
|
# @private used to cache frequently-used regular expressions
|
14
24
|
@@phone_regexp_cache = {}
|
15
25
|
|
@@ -30,14 +40,14 @@ module Phonelib
|
|
30
40
|
@@default_country = nil
|
31
41
|
|
32
42
|
# getter method for default_country variable
|
33
|
-
# @return [String
|
43
|
+
# @return [String,Symbol,Array<String,Symbol>,nil] Default country ISO2 code or codes used for parsing
|
34
44
|
def default_country
|
35
45
|
@@default_country
|
36
46
|
end
|
37
47
|
|
38
48
|
# setter method for default_country variable
|
39
|
-
# @param country [String
|
40
|
-
# @return [String
|
49
|
+
# @param country [String,Symbol,Array<String,Symbol>] Default country ISO2 code or codes used for parsing
|
50
|
+
# @return [String,Symbol,Array<String,Symbol>] Default country ISO2 code or codes used for parsing
|
41
51
|
def default_country=(country)
|
42
52
|
@@default_country = country
|
43
53
|
end
|
@@ -107,6 +117,22 @@ module Phonelib
|
|
107
117
|
@@strict_check = strict
|
108
118
|
end
|
109
119
|
|
120
|
+
# @private don't use plus sign for automatic country change
|
121
|
+
@@ignore_plus = false
|
122
|
+
|
123
|
+
# getter for ignore plus flag
|
124
|
+
# @return [Boolean] Flag defines whether to reset country in case number has + and country prefix doesn't match
|
125
|
+
def ignore_plus
|
126
|
+
@@ignore_plus
|
127
|
+
end
|
128
|
+
|
129
|
+
# setter for ignore plus flag
|
130
|
+
# @param ignore_plus [Boolean] ignore plus sign or not
|
131
|
+
# @return [Boolean] Flag defines whether to ignore plus for country reset during validations in case country prefix doesn't match
|
132
|
+
def ignore_plus=(ignore_plus)
|
133
|
+
@@ignore_plus = ignore_plus
|
134
|
+
end
|
135
|
+
|
110
136
|
# @private sanitizing regex, matching symbols will get removed from parsed number, must be string
|
111
137
|
@@sanitize_regex = '[^0-9]+'
|
112
138
|
|
@@ -163,7 +189,7 @@ module Phonelib
|
|
163
189
|
def add_additional_regex(country, type, national_regex)
|
164
190
|
return unless Phonelib::Core::TYPES_DESC.keys.include?(type.to_sym)
|
165
191
|
return unless national_regex.is_a?(String)
|
166
|
-
@@phone_data = nil
|
192
|
+
@@phone_data = @@data_by_country_codes = nil
|
167
193
|
@@additional_regexes[country.to_s.upcase] ||= {}
|
168
194
|
@@additional_regexes[country.to_s.upcase][type] ||= []
|
169
195
|
@@additional_regexes[country.to_s.upcase][type] << national_regex
|
@@ -19,6 +19,48 @@ module Phonelib
|
|
19
19
|
|
20
20
|
# countries that can have double country prefix in number
|
21
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
|
+
'UM' => 'US',
|
49
|
+
'VA' => 'IT',
|
50
|
+
'VC' => 'US',
|
51
|
+
'VG' => 'US',
|
52
|
+
'VI' => 'US',
|
53
|
+
'YT' => 'RE',
|
54
|
+
'AG' => 'US',
|
55
|
+
'AI' => 'US',
|
56
|
+
'AS' => 'US',
|
57
|
+
'AX' => 'FI',
|
58
|
+
'BB' => 'US',
|
59
|
+
'BL' => 'GP',
|
60
|
+
'BM' => 'US',
|
61
|
+
'BQ' => 'CW',
|
62
|
+
'BS' => 'US',
|
63
|
+
}
|
22
64
|
|
23
65
|
# main data file in repo
|
24
66
|
MAIN_FILE = 'resources/PhoneNumberMetadata.xml'
|
@@ -55,6 +97,7 @@ module Phonelib
|
|
55
97
|
import_main_data
|
56
98
|
import_short_data
|
57
99
|
import_alternate_formats
|
100
|
+
process_format_links
|
58
101
|
import_geocoding_data
|
59
102
|
import_timezone_data
|
60
103
|
import_carrier_data
|
@@ -115,6 +158,15 @@ module Phonelib
|
|
115
158
|
end
|
116
159
|
end
|
117
160
|
|
161
|
+
# some countries missing formats, and are linking them to another countries
|
162
|
+
def process_format_links
|
163
|
+
FORMAT_SHARING.each do |destination, source|
|
164
|
+
next unless @data[destination]
|
165
|
+
@data[destination][:formats] ||= []
|
166
|
+
@data[destination][:formats] = @data[destination][:formats] + @data[source][:formats]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
118
170
|
# method parses geocoding data dir
|
119
171
|
def import_geocoding_data
|
120
172
|
puts 'IMPORTING GEOCODING DATA'
|
data/lib/phonelib/phone.rb
CHANGED
@@ -178,6 +178,8 @@ module Phonelib
|
|
178
178
|
|
179
179
|
# @private extracts extension from passed phone number if provided
|
180
180
|
def separate_extension(original)
|
181
|
+
return [original, ''] unless Phonelib.extension_separate_symbols
|
182
|
+
|
181
183
|
regex = if Phonelib.extension_separate_symbols.is_a?(Array)
|
182
184
|
cr("#{Phonelib.extension_separate_symbols.join('|')}")
|
183
185
|
else
|
@@ -16,8 +16,31 @@ 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? }
|
@@ -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 ||= {}
|
@@ -103,15 +124,22 @@ module Phonelib
|
|
103
124
|
#
|
104
125
|
# * +phone+ - phone number for parsing
|
105
126
|
def detect_and_parse(phone, country)
|
106
|
-
|
107
|
-
|
127
|
+
countries_data = country_code_candidates_for(phone).flat_map { |code|
|
128
|
+
Phonelib.data_by_country_codes[code] || []
|
129
|
+
}
|
130
|
+
countries_data.each_with_object({}) do |data, result|
|
131
|
+
key = data[:id]
|
108
132
|
parsed = parse_single_country(phone, data)
|
109
133
|
if (!Phonelib.strict_double_prefix_check || key == country) && double_prefix_allowed?(data, phone, parsed && parsed[key])
|
110
134
|
parsed = parse_single_country(changed_dp_phone(key, phone), data)
|
111
135
|
end
|
112
136
|
result.merge!(parsed) unless parsed.nil?
|
113
|
-
end
|
114
|
-
|
137
|
+
end.compact
|
138
|
+
end
|
139
|
+
|
140
|
+
def country_code_candidates_for(phone)
|
141
|
+
stripped_phone = phone.gsub(/^(#{Phonelib.phone_data_int_prefixes})/, '')
|
142
|
+
((1..3).map { |length| phone[0, length] } + (1..3).map { |length| stripped_phone[0, length] }).uniq
|
115
143
|
end
|
116
144
|
|
117
145
|
# Create phone representation in e164 format
|
@@ -3,6 +3,16 @@ 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
|
+
matched_countries = country_or_default_country(nil) & result.keys
|
11
|
+
result = result.keep_if {|k, _v| matched_countries.include?(k) } if matched_countries
|
12
|
+
Hash[result.take(1)]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
def original_starts_with_plus?
|
7
17
|
original_s[0] == Core::PLUS_SIGN
|
8
18
|
end
|
@@ -24,7 +34,7 @@ module Phonelib
|
|
24
34
|
# defines if to validate against single country or not
|
25
35
|
def passed_country(country)
|
26
36
|
code = country_prefix(country)
|
27
|
-
if Core::PLUS_SIGN == @original[0] && code && !sanitized.start_with?(code)
|
37
|
+
if !Phonelib.ignore_plus && Core::PLUS_SIGN == @original[0] && code && !sanitized.start_with?(code)
|
28
38
|
# in case number passed with + but it doesn't start with passed
|
29
39
|
# country prefix
|
30
40
|
country = nil
|
@@ -48,7 +58,7 @@ module Phonelib
|
|
48
58
|
def country_can_dp?(country)
|
49
59
|
Phonelib.phone_data[country] &&
|
50
60
|
Phonelib.phone_data[country][Core::DOUBLE_COUNTRY_PREFIX_FLAG] &&
|
51
|
-
!original_starts_with_plus?
|
61
|
+
!original_starts_with_plus? && original_s.start_with?(Phonelib.phone_data[country][Core::COUNTRY_CODE])
|
52
62
|
end
|
53
63
|
|
54
64
|
# changes phone to with/without double country prefix
|
@@ -58,6 +68,7 @@ module Phonelib
|
|
58
68
|
|
59
69
|
country_code = Phonelib.phone_data[country][Core::COUNTRY_CODE]
|
60
70
|
if phone.start_with? country_code * 2
|
71
|
+
# remove double prefix in case it is there
|
61
72
|
phone.gsub(cr("^#{country_code}"), '')
|
62
73
|
else
|
63
74
|
"#{country_code}#{phone}"
|
@@ -90,7 +101,11 @@ module Phonelib
|
|
90
101
|
# * +country+ - country passed for parsing
|
91
102
|
def country_or_default_country(country)
|
92
103
|
country ||= (original_starts_with_plus? ? nil : Phonelib.default_country)
|
93
|
-
|
104
|
+
if country.is_a?(Array)
|
105
|
+
country.compact.map { |e| e.to_s.upcase }
|
106
|
+
else
|
107
|
+
[country && country.to_s.upcase]
|
108
|
+
end
|
94
109
|
end
|
95
110
|
|
96
111
|
# constructs full regex for phone validation for provided phone data
|
@@ -22,8 +22,8 @@ module Phonelib
|
|
22
22
|
return nil if sanitized.nil? || sanitized.empty?
|
23
23
|
if valid?
|
24
24
|
@national_number
|
25
|
-
elsif
|
26
|
-
sanitized[
|
25
|
+
elsif data_country_code && sanitized.start_with?(data_country_code)
|
26
|
+
sanitized[data_country_code.size..-1]
|
27
27
|
else
|
28
28
|
sanitized
|
29
29
|
end
|
@@ -32,8 +32,17 @@ module Phonelib
|
|
32
32
|
# Returns the country code from the original phone number.
|
33
33
|
# @return [String] matched country phone code
|
34
34
|
def country_code
|
35
|
-
@country_code
|
36
|
-
|
35
|
+
return @country_code if @country_code
|
36
|
+
|
37
|
+
code = Phonelib.phone_data[country] && Phonelib.phone_data[country][Core::COUNTRY_CODE]
|
38
|
+
return @country_code = code unless code == '1' && Phonelib.phone_data[country][Core::LEADING_DIGITS]
|
39
|
+
|
40
|
+
match = e164.match(/\A\+(1(#{Phonelib.phone_data[country][Core::LEADING_DIGITS]}))/)
|
41
|
+
if match
|
42
|
+
@country_code = match[1]
|
43
|
+
else
|
44
|
+
@country_code = '1'
|
45
|
+
end
|
37
46
|
end
|
38
47
|
|
39
48
|
# Returns e164 formatted phone number. Method can receive single string parameter that will be defined as prefix
|
@@ -44,7 +53,7 @@ module Phonelib
|
|
44
53
|
prefix = formatted if formatted.is_a?(String)
|
45
54
|
return nil if sanitized.empty?
|
46
55
|
return "#{prefix}#{country_prefix_or_not}#{sanitized}" unless valid?
|
47
|
-
return "#{prefix}#{
|
56
|
+
return "#{prefix}#{data_country_code}#{@national_number}" unless formatted
|
48
57
|
|
49
58
|
fmt = @data[country][:format]
|
50
59
|
national = @national_number
|
@@ -53,7 +62,7 @@ module Phonelib
|
|
53
62
|
national = fmt.gsub(/\$\d/) { |el| matches[el[1].to_i] } unless fmt == 'NA'
|
54
63
|
end
|
55
64
|
|
56
|
-
"#{prefix}#{
|
65
|
+
"#{prefix}#{data_country_code} #{national}"
|
57
66
|
end
|
58
67
|
|
59
68
|
# returns national formatted number with extension added
|
@@ -109,6 +118,10 @@ module Phonelib
|
|
109
118
|
|
110
119
|
private
|
111
120
|
|
121
|
+
def data_country_code
|
122
|
+
@data_country_code ||= Phonelib.phone_data[country] && Phonelib.phone_data[country][Core::COUNTRY_CODE]
|
123
|
+
end
|
124
|
+
|
112
125
|
# @private defines if phone can have area code
|
113
126
|
def area_code_possible?
|
114
127
|
return false if impossible?
|
@@ -124,8 +137,8 @@ module Phonelib
|
|
124
137
|
|
125
138
|
# @private defines whether to put country prefix or not
|
126
139
|
def country_prefix_or_not
|
127
|
-
return '' unless
|
128
|
-
sanitized.start_with?(
|
140
|
+
return '' unless data_country_code
|
141
|
+
sanitized.start_with?(data_country_code) ? '' : data_country_code
|
129
142
|
end
|
130
143
|
|
131
144
|
# @private returns extension with separator defined
|
data/lib/phonelib/version.rb
CHANGED
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.8.2
|
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: 2023-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: benchmark-ips
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: benchmark-memory
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: rack-cache
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|