valkey-objects 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66451b3bbdc217925b068c50c8cdcd5cd392a6ddef99adbc7300c683c112d152
4
- data.tar.gz: eb06049f2987c87b8cb7fb188e15960fab83d2f7a820205b3ddd06df1ed11828
3
+ metadata.gz: 32d09321f670991b444f2c90843694b054596be914e071f76598019bf95302d1
4
+ data.tar.gz: b2cff91d109c421204ea924aa51eed2e1bd5a7d50ec7baced09926d6945485d0
5
5
  SHA512:
6
- metadata.gz: 78d4470e2aa1cc2b9763265c7a940f4f2da58798460fbce998e2aedd32cdcd6136accca257d83719328e59011b6da185c59f590863642d430488966b9a77cb9e
7
- data.tar.gz: ad6b0974b14ebd9bc022aa259a4a953556d5ec567d370a0335b279fc695f655713cba4d0499e8cb7d6bc15e610a5ba4918d8a81bdeca4ce8820bd0d65f8f6439
6
+ metadata.gz: b0b9306307f46e9ef2d4e495ddf08f6be8113f43a66568e679fa53a615cff36e8ad468657a126fb5cd302c50c0bb9c0aae0ee649b89cdb8f9f393747827b9eab
7
+ data.tar.gz: 2c5dc3f7a3d98860dc7cfac4b07c1778394669bac0349b8485a237322559262823adc8e6786f161b4b4cb1c996d4933402d99dfdda0b9f4823d237189d618eb3
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Valkey
4
4
  module Objects
5
- VERSION = "0.2.0"
5
+ VERSION = "0.2.2"
6
6
  end
7
7
  end
@@ -5,8 +5,14 @@ require_relative "objects/version"
5
5
  require 'redis-client'
6
6
  require 'json'
7
7
  require 'ruby-duration'
8
+ require 'amatch'
8
9
  require 'ap'
9
10
  module VK
11
+
12
+ @@XX = {}
13
+
14
+
15
+
10
16
  def self.included(x)
11
17
  x.extend VK
12
18
  end
@@ -16,6 +22,8 @@ module VK
16
22
  # Example:
17
23
  # class ExmpleObject
18
24
  # include VK
25
+ #
26
+ ## Add Object Containers by Value Type:
19
27
  # value :myValue
20
28
  # counter :myCounter
21
29
  # hashkey :myHashKey
@@ -23,51 +31,84 @@ module VK
23
31
  # set :mySet
24
32
  # queue :myQueue
25
33
  # place :myPlace
26
- # pipe :myPipe
27
34
  # toggle :myToggle
35
+ # ticker :myTicker
36
+ # entry :myEntry
37
+ #
38
+ ## Add an Object Container With an Implicit Expiration:
39
+ # value :myExpiringValue, ttl: (seconds to live without interaction)
40
+ #
28
41
  # def initialize k
29
42
  # @id = k
30
43
  # end
31
44
  # end
32
- #
33
- # Instantiation: @obj = ExampleObject.new('object id...')
45
+ ##
46
+ # Create the Object:
47
+ # @obj = ExampleObject.new('object id...')
48
+ ##
49
+ # For all object methods:
50
+ # @obj.myObjectContainer.expire(seconds)
51
+ # @obj.myObjectContainer.delete!
52
+ #
34
53
  xx = x.name.gsub("::", "-")
35
54
  ##
55
+ # Object Method Types:
56
+ ##
57
+ # A String Value
58
+ ##
36
59
  # value :myValue
37
- # @obj.myValue => A string
60
+ # @obj.myValue
61
+ # @obj.myValue.exist?
38
62
  # @obj.myValue.value = "my value"
39
63
  # @obj.myValue.value => "my value"
40
- define_method(:value) { |k| define_method(k.to_sym) { V.new(%[#{xx}:value:#{k}:#{@id}]) } };
64
+ define_method(:value) { |k, h={}| define_method(k.to_sym) { VALUE.new(%[#{xx}:value:#{k}:#{@id}], h) } };
65
+ ##
66
+ # A Number Value
41
67
  ##
42
- # counter :myCounter => A number
68
+ # counter :myCounter
43
69
  # @obj.myCounter
70
+ # @obj.myCounter.exist?
44
71
  # @obj.myCounter.value = number
45
- # @obj.myCounter.value => ...
72
+ # @obj.myCounter.value => number
46
73
  # @obj.myCounter.incr number
47
74
  # @obj.myCounter.decr number
48
75
  #
49
- define_method(:counter) { |k| define_method(k.to_sym) { C.new(%[#{xx}:counter:#{k}:#{@id}]); } };
76
+ define_method(:counter) { |k, h={}| define_method(k.to_sym) { COUNTER.new(%[#{xx}:counter:#{k}:#{@id}], h); } };
50
77
  ##
51
- #
52
- define_method(:timestamp) { |k| define_method(k.to_sym) { N.new(%[#{xx}:counter:#{k}:#{@id}]) } }
53
- ##
54
- # hashkey :myHashKey => The ubiquitous Ruby Hash in valkey/redis
78
+ # An Epoch Value
79
+ ##
80
+ # timestamp :myTimestamp
81
+ # @obj.myTimestamp
82
+ # @obj.myTimestamp.exist?
83
+ # @obj.myTimestamp.value!
84
+ # @obj.myTimestamp.value => epoch
85
+ # @obj.myTimestamp.ago => Seconds since epoch
86
+ # @obj.myTimestamp.to_time => Time object
87
+ define_method(:timestamp) { |k, h={}| define_method(k.to_sym) { TIMESTAMP.new(%[#{xx}:timestamp:#{k}:#{@id}], h) } }
88
+ ##
89
+ # A Hash Value
90
+ ##
91
+ # hashkey :myHashKey
55
92
  # @obj.myHashKey
56
93
  # @obj.myHashKey[:key] = value
57
- # @obj.myHashKey[:key] => ...
94
+ # @obj.myHashKey[:key] => "value"
58
95
  #
59
- define_method(:hashkey) { |k| define_method(k.to_sym) { H.new(%[#{xx}:hash:#{k}:#{@id}]); } };
60
- ##
61
- # sortedset :mySortedSet => A ranked collection of members
96
+ define_method(:hashkey) { |k, h={}| define_method(k.to_sym) { HASH.new(%[#{xx}:hashkey:#{k}:#{@id}], h); } };
97
+ ##
98
+ # A Sorted Set Value
99
+ ##
100
+ # sortedset :mySortedSet
62
101
  # @obj.mySortedSet
63
102
  # @obj.mySortedSet[:key] = value
64
103
  # @obj.mySortedSet[:key] => ...
65
104
  # @obj.mySortedSet.value { |key, i| ... }
66
105
  # @obj.mySortedSet.poke key, number
67
106
  #
68
- define_method(:sortedset) { |k| define_method(k.to_sym) { S.new(%[#{xx}:sortedset:#{k}:#{@id}]); } };
69
- ##
70
- # set :mySet => A collect of unique members
107
+ define_method(:sortedset) { |k, h={}| define_method(k.to_sym) { SORTEDSET.new(%[#{xx}:sortedset:#{k}:#{@id}], h); } };
108
+ ##
109
+ # A Collection of Values
110
+ ##
111
+ # set :mySet
71
112
  # @obj.mySet
72
113
  # @obj.mySet << "x"
73
114
  # @obj.myset.rm "x"
@@ -76,17 +117,21 @@ module VK
76
117
  # @obj.myset["pattern"]
77
118
  # @obj.mySet.value { |key, i| ... }
78
119
  #
79
- define_method(:set) { |k| define_method(k.to_sym) { G.new(%[#{xx}:set:#{k}:#{@id}]); } };
80
- ##
81
- # queue :myQueue => An array with push and pop utility
120
+ define_method(:set) { |k, h={}| define_method(k.to_sym) { SET.new(%[#{xx}:set:#{k}:#{@id}], h); } };
121
+ ##
122
+ # A List of Values
123
+ ##
124
+ # queue :myQueue
82
125
  # @obj.myQueue
83
126
  # @obj.myQueue << "x"
84
127
  # @obj.myQueue.front => "x" and pop
85
128
  # @obj.myQueue.value { |key, i| ... }
86
129
  #
87
- define_method(:queue) { |k| define_method(k.to_sym) { Q.new(%[#{xx}:queue:#{k}:#{@id}]); } };
88
- ##
89
- # place :myPlace => GPS Coordinates
130
+ define_method(:queue) { |k, h={}| define_method(k.to_sym) { QUEUE.new(%[#{xx}:queue:#{k}:#{@id}], h); } };
131
+ ##
132
+ # A Collection of Places
133
+ ##
134
+ # place :myPlace
90
135
  # @obj.myPlace
91
136
  # @obj.myPlace.add "key", longitude, latitude
92
137
  # @obj.myPlace["key"] => { longitude: xx, latitude: yy }
@@ -94,24 +139,45 @@ module VK
94
139
  # @obj.myPlace.radius longitude, latitude, distance
95
140
  # @obj.myPlace.value { |key, i| ... }
96
141
  #
97
- define_method(:place) { |k| define_method(k.to_sym) { P.new(%[#{xx}:place:#{k}:#{@id}]); } };
98
- ##
99
- # pipe :myPipe => Subscibe and handle, and publish.
100
- # @obj.myPipe
101
- # @obj.myPipe.on { |msg| ... }
102
- # @obj.myPipe << "input" => publish { input: "input" }
103
- # @obj.myPipe << ["input","input"] => publish { inputs: ["input", "input"] }
104
- # @obj.myPipe << {} => publish {}
105
- #
106
- define_method(:pipe) { |k| define_method(k.to_sym) { B.new(%[#{xx}:pipe:#{k}:#{@id}]); } };
107
- ##
108
- # toggle :myToggle => Boolean toggle.
142
+ define_method(:place) { |k, h={}| define_method(k.to_sym) { PLACE.new(%[#{xx}:place:#{k}:#{@id}], h); } };
143
+ ##
144
+ # A Boolean Value
145
+ ##
146
+ # toggle :myToggle
109
147
  # @obj.myToggle
110
- # @obj.value = bool
111
- # @obj.value => ...
112
- # @obj.value! => value = !value
148
+ # @obj.myToggle.exist?
149
+ # @obj.myToggle.value = bool
150
+ # @obj.myToggle.value => ...
151
+ # @obj.myToggle.value! => value = !value
113
152
  #
114
- define_method(:toggle) { |k| define_method(k.to_sym) { T.new(%[#{xx}:toggle:#{k}:#{@id}]); } };
153
+ define_method(:toggle) { |k, h={}| define_method(k.to_sym) { TOGGLE.new(%[#{xx}:toggle:#{k}:#{@id}], h); } };
154
+ ##
155
+ # A Sorted Hash of Values
156
+ ##
157
+ # ticker :myTicker
158
+ # @obj.myTicker
159
+ # @obj.myTicker[:key] = value
160
+ # @obj.myTicker[:key] => "value"
161
+ # @obj.myticker.value { |i,e| ... }
162
+ define_method(:ticker) { |k, h={}| define_method(k.to_sym) { SORTEDHASH.new(%[#{xx}:ticker:#{k}:#{@id}], h); } };
163
+ ##
164
+ # A List of Hashes
165
+ ##
166
+ # entry :myEntry
167
+ # @obj.myEntry
168
+ # @obj.myEntry << { key: 'value', ... }
169
+ # @obj.myEntry.value { |i,e| ... }
170
+ define_method(:entry) { |k, h={}| define_method(k.to_sym) { HASHLIST.new(%[#{xx}:entry:#{k}:#{@id}], h); } };
171
+ ##
172
+ # A list of Strings
173
+ ##
174
+ # vector :myVector
175
+ # @obj.myVector
176
+ # @obj.myVector << "An Entry of Text."
177
+ # @obj.myVector.value { |i,e| ... }
178
+ # @obj.myvector[0] = "An Entry of Text."
179
+ define_method(:vector) { |k, h={}| define_method(k.to_sym) { VECTOR.new(%[#{xx}:vector:#{k}:#{@id}], h); } };
180
+
115
181
  end
116
182
 
117
183
  def id
@@ -161,11 +227,15 @@ module VK
161
227
  def self.redis
162
228
  RedisClient.config(host: "127.0.0.1", port: 6379, db: 0).new_client
163
229
  end
164
-
230
+
165
231
  class O
166
232
  attr_reader :key
167
- def initialize k
233
+ def initialize k, h={}
168
234
  @key = k
235
+ @opts = h
236
+ if @opts.has_key?(:ttl)
237
+ expire @opts[:ttl]
238
+ end
169
239
  end
170
240
  def delete!
171
241
  VK.redis.call("DEL", key);
@@ -175,13 +245,19 @@ module VK
175
245
  end
176
246
  end
177
247
 
178
- class N < O
248
+ class TIMESTAMP < O
179
249
  def value
180
250
  VK.redis.call("GET", key).to_i;
251
+ if @opts.has_key?(:flush) == true
252
+ delete!
253
+ end
181
254
  end
182
255
  def value!
183
256
  VK.redis.call("SET", key, "#{VK.clock.to_i}");
184
257
  end
258
+ def exist?
259
+ VK.redis.call("GET", key) ? true : false
260
+ end
185
261
  def ago
186
262
  VK.clock.to_i - value;
187
263
  end
@@ -190,10 +266,16 @@ module VK
190
266
  end
191
267
  end
192
268
 
193
- class T < O
269
+ class TOGGLE < O
194
270
  def value
195
- VK.redis.call("GET", key) == 'true' ? true : false
271
+ VK.redis.call("GET", key) == 'true' ? true : false
272
+ if @opts.has_key?(:flush) == true
273
+ delete!
274
+ end
196
275
  end
276
+ def exist?
277
+ VK.redis.call("GET", key) ? true : false
278
+ end
197
279
  def value= x
198
280
  VK.redis.call("SET", key, "#{x.to_s}")
199
281
  end
@@ -206,42 +288,19 @@ module VK
206
288
  end
207
289
  end
208
290
 
209
- class B < O
210
- def on &b
211
- pubsub = VK.redis.pubsub
212
- pubsub.call("SUBSCRIBE", key)
213
- Process.detach( fork do
214
- loop do
215
- if m = pubsub.next_event(0)
216
- cn, ty, na, id = key.split(":")
217
- if m[0] == "message"
218
- b.call({ stub: na, object: cn.gsub("-", "::"), type: ty, id: id, event: m[0], data: JSON.parse(m[2]) })
219
- else
220
- ap({ stub: na, object: cn.gsub("-", "::"), type: ty, id: id, event: m[0], data: m[2] })
221
- end
222
- end
223
- end
224
- end
225
- );
226
- end
227
- def << x
228
- if x.class == String
229
- VK.redis.call("PUBLISH", key, JSON.generate({ input: x }))
230
- elsif x.class == Array
231
- VK.redis.call("PUBLISH", key, JSON.generate({ inputs: x }))
232
- elsif x.class == Hash
233
- VK.redis.call("PUBLISH", key, JSON.generate(x))
234
- end
235
- end
236
- end
237
-
238
- class V < O
291
+ class VALUE < O
239
292
  def value
240
293
  VK.redis.call("GET", key)
294
+ if @opts.has_key?(:flush) == true
295
+ delete!
296
+ end
241
297
  end
242
298
  def value= x
243
299
  VK.redis.call("SET", key, x)
244
300
  end
301
+ def exist?
302
+ VK.redis.call("GET", key) ? true : false
303
+ end
245
304
  def match r, &b
246
305
  m = Regexp.new(r).match(value)
247
306
  if block_given?
@@ -251,8 +310,54 @@ module VK
251
310
  end
252
311
  end
253
312
  end
313
+
314
+ class VECTOR < O
315
+ include Amatch
316
+ def value &b
317
+ a = []
318
+ VK.redis.call("LRANGE", key, 0, -1).each_with_index { |e, i|
319
+ if block_given?
320
+ a << b.call(i, VK.redis.call("GET", e))
321
+ else
322
+ a << VK.redis.call("GET", e)
323
+ end
324
+ if @opts.has_key?(:flush) == true
325
+ VK.redis.call("DEL", e);
326
+ end
327
+ }
328
+ if @opts.has_key?(:flush) == true
329
+ delete!
330
+ end
331
+ return a
332
+ end
333
+ def [] k
334
+ VK.redis.call("GET", "#{@key}-#{k}");
335
+ end
336
+ def << i
337
+ kk = %[#{@key}-#{VK.redis.call("LLEN",@key)}]
338
+ VK.redis.call("SET", kk, i);
339
+ VK.redis.call("RPUSH", key, kk)
340
+ end
341
+ def nearest p
342
+ h = {}
343
+ value { |i,v|
344
+ h[i] = {
345
+ value: v,
346
+ levenshtein: p.levenshtein_similar(v),
347
+ damerau: p.damerau_levenshtein_similar(v),
348
+ hamming: p.hamming_similar(v),
349
+ distance: p.pair_distance_similar(v),
350
+ subsequence: p.longest_subsequence_similar(v),
351
+ substring: p.longest_substring_similar(v),
352
+ jaro: p.jaro_similar(v),
353
+ winkler: p.jarowinkler_similar(v)
354
+ }
355
+ }
356
+ return h
357
+ end
358
+ end
254
359
 
255
- class C < O
360
+ class COUNTER < O
256
361
  def incr n
257
362
  VK.redis.call("SET", key, value + n.to_f)
258
363
  end
@@ -261,27 +366,36 @@ module VK
261
366
  end
262
367
  def value
263
368
  VK.redis.call("GET", key).to_f
369
+ if @opts.has_key?(:flush) == true
370
+ delete!
371
+ end
264
372
  end
265
373
  def value= n
266
374
  VK.redis.call("SET", key, n.to_f)
267
375
  end
376
+ def exist?
377
+ VK.redis.call("GET", key) ? true : false
378
+ end
268
379
  end
269
380
 
270
- class H < O
381
+ class HASH < O
271
382
  def [] k
272
383
  VK.redis.call("HGET", key, k);
273
384
  end
274
385
  def []= k,v
275
- VK.redis.call("HMSET", key, k, v);
386
+ VK.redis.call("HSET", key, k, v);
276
387
  end
277
388
  def to_h
278
389
  VK.redis.call("HGETALL", key);
279
390
  end
280
391
  end
281
392
 
282
- class Q < O
393
+ class QUEUE < O
283
394
  def value &b
284
395
  VK.redis.call("LRANGE", key, 0, -1).each_with_index { |e, i| b.call(i, e) }
396
+ if @opts.has_key?(:flush) == true
397
+ delete!
398
+ end
285
399
  end
286
400
  def length
287
401
  VK.redis.call("LLEN", key)
@@ -294,9 +408,12 @@ module VK
294
408
  end
295
409
  end
296
410
 
297
- class S < O
411
+ class SORTEDSET < O
298
412
  def value &b
299
413
  VK.redis.call("ZREVRANGE", key, 0, -1, 'WITHSCORES').each_with_index { |e, i| b.call(i, e) }
414
+ if @opts.has_key?(:flush) == true
415
+ delete!
416
+ end
300
417
  end
301
418
  def [] k
302
419
  VK.redis.call("ZSCORE", key, k).to_f;
@@ -309,9 +426,20 @@ module VK
309
426
  end
310
427
  end
311
428
 
312
- class G < O
429
+ class SET < O
313
430
  def value &b
314
- VK.redis.call("SMEMBERS", key).each_with_index { |e, i| b.call(i, e) }
431
+ a = Set.new
432
+ VK.redis.call("SMEMBERS", key).each_with_index { |e, i|
433
+ if block_given?
434
+ a << b.call(i, e)
435
+ else
436
+ a << e
437
+ end
438
+ }
439
+ if @opts.has_key?(:flush) == true
440
+ delete!
441
+ end
442
+ return aa
315
443
  end
316
444
  def include? k
317
445
  if VK.redis.call("SMISMEMBER", key, k)[0] == 0
@@ -342,9 +470,20 @@ module VK
342
470
  end
343
471
  end
344
472
 
345
- class P < O
473
+ class PLACE < O
346
474
  def value &b
347
- VK.redis.call("ZRANGE", key, 0, -1).each_with_index { |e, i| b.call(i, e) };
475
+ a = []
476
+ VK.redis.call("ZRANGE", key, 0, -1).each_with_index { |e, i|
477
+ if block_given?
478
+ a << b.call(i, e)
479
+ else
480
+ a << e
481
+ end
482
+ };
483
+ if @opts.has_key?(:flush) == true
484
+ delete!
485
+ end
486
+ return a
348
487
  end
349
488
  def add i, lon, lat
350
489
  VK.redis.call("GEOADD", key, lon, lat, i)
@@ -363,6 +502,68 @@ module VK
363
502
  end
364
503
  end
365
504
 
505
+ class SORTEDHASH < O
506
+ def value &b
507
+ VK.redis.call("ZREVRANGE", key, 0, -1, 'WITHSCORES').each_with_index { |e, i|
508
+ kx = %[#{@key}-#{e[0]}]
509
+ a = []
510
+ if block_given?
511
+ b.call(i, { key: e[0], value: VK.redis.call("GET", kx), score: e[1] } )
512
+ else
513
+ a << { key: e[0], value: VK.redis.call("GET", kx), score: e[1] }
514
+ end
515
+ if @opts.has_key?(:flush) == true
516
+ VK.redis.call("DEL", kx)
517
+ end
518
+ }
519
+ if @opts.has_key?(:flush) == true
520
+ delete!
521
+ end
522
+ return a
523
+ end
524
+ def [] k
525
+ kx = %[#{@key}-#{k}]
526
+ VK.redis.call("GET", kx)
527
+ end
528
+ def []= k, v
529
+ kx = %[#{@key}-#{k}]
530
+ VK.redis.call("SET", kx, v)
531
+ VK.redis.call("ZINCRBY", key, 1, k)
532
+ end
533
+ end
534
+
535
+ class HASHLIST < O
536
+ def value &b
537
+ a = []
538
+ VK.redis.call("LRANGE", key, 0, -1).each_with_index { |e, i|
539
+ if block_given?
540
+ a << b.call(i, JSON.parse(VK.redis.call("GET", e)))
541
+ else
542
+ a << JSON.parse(VK.redis.call("GET", e))
543
+ end
544
+ if @opts.has_key?(:flush) == true
545
+ VK.redis.call("DEL", e)
546
+ end
547
+ }
548
+ if @opts.has_key?(:flush) == true
549
+ delete!
550
+ end
551
+ return a
552
+ end
553
+ def length
554
+ VK.redis.call("LLEN", key)
555
+ end
556
+ def [] k
557
+ hx = %[#{key}-#{k}]
558
+ JSON.parse(VK.redis.call("GET", hx));
559
+ end
560
+ def push h={}
561
+ hx = %[#{key}-#{length}]
562
+ VK.redis.call("SET", hx, JSON.generate(h));
563
+ VK.redis.call("RPUSH", key, hx)
564
+ end
565
+ end
566
+
366
567
  def self.flushdb!
367
568
  VK.redis.call("FLUSHDB")
368
569
  end
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency "json"
36
36
  spec.add_dependency "ruby-duration"
37
37
  spec.add_dependency "pry"
38
+ spec.add_dependency "amatch"
38
39
  spec.add_dependency "awesome_print"
39
40
  # For more information and examples about making a new gem, check out our
40
41
  # guide at: https://bundler.io/guides/creating_gem.html
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valkey-objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Olson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-12 00:00:00.000000000 Z
11
+ date: 2025-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis-client
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: amatch
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: awesome_print
71
85
  requirement: !ruby/object:Gem::Requirement