redis-objects 1.3.1 → 1.5.1

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
- SHA1:
3
- metadata.gz: ae3bd1cf4a81eca5bbb34a027f066b2dcbd233d5
4
- data.tar.gz: 03ec3b26287e799061232c37a9604b0b65e52219
2
+ SHA256:
3
+ metadata.gz: 5c7bc592d203647a8b7e9fd574a78eec1ec466e85fef95d30fac6d831f5d086a
4
+ data.tar.gz: e89a8a50ddac32cc8b0fd5692697c21620ef97bac6f28c1841c0e50e9a833429
5
5
  SHA512:
6
- metadata.gz: af1e410ca8fdb1251e4b67c6ff6e051a76ea78804c729b82cc7ba90ced750cc9139c9fbf86d78b2e79476a55c66a7c59733c150f6ff9adb9a9e16bf94ee7daf7
7
- data.tar.gz: 9e8deeb4e39b6ccf713f461eae512870c3fac18d211984583d3ad10814b231515d724aee6c22b9cecd7306b29d2e20f68de77f4f794c3deae3b6fa4d74153a1b
6
+ metadata.gz: 7a91ab932b94a4a36ab4da40d173804b71c46b21c28e917acefb5f1720da1dd60fe3e4c0d06e124c172118789c31fa11f0f4b96b7b27da97cbd8f7a90f01dd6c
7
+ data.tar.gz: d92e900d1fcec537a439e99ad7d311a83ad23c1e5c28ecc84e8922a0c7da56b4fdcfc9cadcb48aca382c4a6c8045dd24ecbeb81d681aa4fcad2c9d13b3cf9a8f
data/.travis.yml CHANGED
@@ -5,9 +5,7 @@ before_install:
5
5
  - gem install bundler
6
6
 
7
7
  rvm:
8
- - 1.9.3
9
- - 2.0.0
10
- - 2.1
11
- - 2.2
12
8
  - 2.3.3
13
9
  - 2.4.0
10
+ - 2.5.1
11
+ - 2.6.4
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,104 @@
1
1
  = Changelog for Redis::Objects
2
2
 
3
+ == 1.5.1 (10 Jul 2021)
4
+
5
+ * Added double-splat for **options to account for Ruby 3.0 [Nate Wiger]
6
+
7
+ * Fix ConnectionPoolProxy Ruby 3.0 compatibility Fix: https://github.com/nateware/redis-objects/pull/258 [Jean byroot Boussier]
8
+
9
+ * Change Redis#exists to Redis#exists? * bump redis version to 4.2 [Alina Hryshchuk]
10
+
11
+ * Local variable `dir` is not in use since 98226b95f35ef455f231692fdb679dfd61200a78 [Akira Matsuda]
12
+
13
+ * Issue 249: when atomic decrbyfloat fails, increment back instead of decrementing again [Slava Samoliuk]
14
+
15
+ * Update documentation to reflect ability to assign values directly [Artin Boghosian]
16
+
17
+ * Allow directly assigning values of lists, hashes and sets [Artin Boghosian]
18
+
19
+
20
+ == 1.5.0 (18 Sep 2019)
21
+
22
+ * updated README on expireat [Nate Wiger]
23
+
24
+ * Add option for using a custom serializer [Tomás Rojas]
25
+
26
+ * DRY up objects to enable custom prefixing when desired [Tomás Rojas]
27
+
28
+ * Allow spop to return multiple members [Evan Paul]
29
+
30
+ * Rename #delete! to #redis_delete_objects [Mattias Pfeiffer]
31
+
32
+ * Make deletion simpler with just 1 call to Redis [Mattias Pfeiffer]
33
+
34
+ * Move `CoreCommands` inclusion to `BaseObject` [Tomás Rojas]
35
+
36
+ * Move `Enumerable` functionality to `EnumerableObject` [Tomás Rojas]
37
+
38
+ * Move `attr_reader`s to `Redis::BaseObject` [Tomás Rojas]
39
+
40
+ == 1.4.3 (7 Oct 2018)
41
+
42
+ * Merge pull request #235 from johnc219/fix/end-time-expiration Add expiration in seconds to obtain end_time [Nate Wiger]
43
+
44
+ * Merge pull request #223 from artinboghosian/compress-redis-value Allow compression of value stored in Redis::Value to save memory on R… [Nate Wiger]
45
+
46
+ * Merge pull request #224 from artinboghosian/sorted-set-missing-operations Fix set operation methods on SortedSets [Nate Wiger]
47
+
48
+ * Merge pull request #233 from tmattia/master Add SortedSet#count alias so it's consistent with Set#count [Nate Wiger]
49
+
50
+ * Merge pull request #236 from nateware/revert-220-threadsafe Revert "Make Redis::Objects.connection thread-safe" [Nate Wiger]
51
+
52
+ * Revert "Make Redis::Objects.connection thread-safe" [Nate Wiger]
53
+
54
+ == 1.4.2 (29 Aug 2018)
55
+
56
+ * Merge pull request #227 from D-system/optimise_lock Optimise lock [Nate Wiger]
57
+
58
+ * Merge pull request #228 from D-system/travis_ruby_2.5 Travis: test against ruby 2.5 [Nate Wiger]
59
+
60
+ * Travis: test against ruby 2.5 [Thomas Brennetot]
61
+
62
+ * Lock: update comment [Thomas Brennetot]
63
+
64
+ * Lock: add backward compatibility [Thomas Brennetot]
65
+
66
+ * Use SET with the NX and the expiration option in a single request [Thomas Brennetot]
67
+
68
+ * Merge pull request #218 from edwardbako/list_pushed_count Return count of lpush & rpush commands [Nate Wiger]
69
+
70
+ * Merge pull request #220 from gammons/threadsafe Make Redis::Objects.connection thread-safe [Nate Wiger]
71
+
72
+ * Make Redis::Objects.connection threadsafe [Grant Ammons]
73
+
74
+ * Return count of lpush & rpush commands [Edward Bako]
75
+
76
+ * Removed support for versions of Ruby < 2.2 [Nate Wiger]
77
+
78
+ == 1.4.1 (Unreleased)
79
+
80
+ * Buggy release that was removed
81
+
82
+ == 1.4.0 (7 Dec 2017)
83
+
84
+ * Bumped dependency to redis.rb 4.0 [Nate Wiger]
85
+
86
+ == 1.3.1 (29 Aug 2017)
87
+
88
+ * Merge pull request #213 from onk/feature/proc_expireat Allow to set proc for expireat [Nate Wiger]
89
+
90
+ * Merge pull request #212 from yuzixun/hotfix/counter modify Counter#nil? [Nate Wiger]
91
+
92
+ * Merge pull request #207 from i2bskn/improve_bulk_get Reduce query to Redis. [Nate Wiger]
93
+
94
+ * Merge pull request #209 from yuzixun/hotfix/hash_key/bulk_related fix error when fields/keys is an array [Nate Wiger]
95
+
96
+ * Use pre-calculated symbols for instance_variable_(get|set) for performance #211 [Nate Wiger]
97
+
98
+ * Weird inheriting from version AR::Migration thingy [Nate Wiger]
99
+
100
+ * Reduce query to Redis. Don't query to Redis if #bulk_get/#bulk_values arguments is empty. [i2bskn]
101
+
3
102
  == 1.3.0 (11 Mar 2017)
4
103
 
5
104
  * handle two Redis::Counter objects adding/subtracting [Nate Wiger]
data/README.md CHANGED
@@ -9,7 +9,7 @@ This is **not** an ORM. People that are wrapping ORM’s around Redis are missin
9
9
  The killer feature of Redis is that it allows you to perform _atomic_ operations
10
10
  on _individual_ data structures, like counters, lists, and sets. The **atomic** part is HUGE.
11
11
  Using an ORM wrapper that retrieves a "record", updates values, then sends those values back,
12
- _removes_ the atomicity, cutting the nuts off the major advantage of Redis. Just use MySQL, k?
12
+ _removes_ the atomicity, and thus the major advantage of Redis. Just use MySQL, k?
13
13
 
14
14
  This gem provides a Rubyish interface to Redis, by mapping [Redis data types](http://redis.io/commands)
15
15
  to Ruby objects, via a thin layer over the `redis` gem. It offers several advantages
@@ -144,6 +144,7 @@ Familiar Ruby array operations Just Work (TM):
144
144
  @team.on_base.shift
145
145
  @team.on_base.length # 1
146
146
  @team.on_base.delete('player2')
147
+ @team.on_base = ['player1', 'player2'] # ['player1', 'player2']
147
148
  ~~~
148
149
 
149
150
  Sets work too:
@@ -157,6 +158,15 @@ Sets work too:
157
158
  puts player
158
159
  end
159
160
  player = @team.outfielders.detect{|of| of == 'outfielder2'}
161
+ @team.outfielders = ['outfielder1', 'outfielder3'] # ['outfielder1', 'outfielder3']
162
+ ~~~
163
+
164
+ Hashes work too:
165
+
166
+ ~~~ruby
167
+ @team.pitchers_faced['player1'] = 'pitcher2'
168
+ @team.pitchers_faced['player2'] = 'pitcher1'
169
+ @team.pitchers_faced = { 'player1' => 'pitcher2', 'player2' => 'pitcher1' }
160
170
  ~~~
161
171
 
162
172
  And you can do unions and intersections between objects (kinda cool):
@@ -261,6 +271,18 @@ Complex data is no problem with :marshal => true:
261
271
  puts @newest.value['username']
262
272
  ~~~
263
273
 
274
+ Compress data to save memory usage on Redis with :compress => true:
275
+
276
+ ~~~ruby
277
+ @account = Account.create!(params[:account])
278
+ @marshaled_value = Redis::Value.new('marshaled', :marshal => true, :compress => true)
279
+ @marshaled_value.value = @account.attributes
280
+ @unmarshaled_value = Redis::Value.new('unmarshaled', :compress => true)
281
+ @unmarshaled_value = 'Really Long String'
282
+ puts @marshaled_value.value['username']
283
+ puts @unmarshaled_value.value
284
+ ~~~
285
+
264
286
  Lists
265
287
  -----
266
288
  Lists work just like Ruby arrays:
@@ -538,20 +560,40 @@ Use :expiration and :expireat options to set default expiration.
538
560
 
539
561
  ~~~ruby
540
562
  value :value_with_expiration, :expiration => 1.hour
541
- value :value_with_expireat, :expireat => Time.now + 1.hour
563
+ value :value_with_expireat, :expireat => lambda { Time.now + 1.hour }
542
564
  ~~~
543
565
 
544
- :warning: `expireat` is evaluated at class load time.
545
- In this example, it will be one hour after evaluating class, not after one hour after setting value.
566
+ :warning: In the above example, `expiration` is evaluated at class load time.
567
+ In this example, it will be one hour after loading the class, not after one hour
568
+ after setting a value. If you want to expire one hour after setting the value,
569
+ please use `:expireat` with `lambda`.
546
570
 
547
- If you want to expire one hour after setting the value. please use `lambda`.
571
+ Custom serialization
572
+ --------------------
573
+ You can customize how values are serialized by setting `serializer: CustomSerializer`.
574
+ The default is `Marshal` from the standard lib, but it can be anything that responds to `dump` and
575
+ `load`. `JSON` and `YAML` are popular options.
576
+
577
+ If you need to pass extra arguments to `dump` or `load`, you can set
578
+ `marshal_dump_args: { foo: 'bar' }` and `marshal_load_args: { foo: 'bar' }` respectively.
548
579
 
549
580
  ~~~ruby
550
- value :value_with_expireat, :expireat => lambda { Time.now + 1.hour }
581
+ class CustomSerializer
582
+ def self.dump(value)
583
+ # custom code for serializing
584
+ end
585
+
586
+ def self.load(value)
587
+ # custom code for deserializing
588
+ end
589
+ end
590
+
591
+ @account = Account.create!(params[:account])
592
+ @newest = Redis::Value.new('custom_serializer', marshal: true, serializer: CustomSerializer)
593
+ @newest.value = @account.attributes
551
594
  ~~~
552
595
 
553
596
  Author
554
597
  =======
555
- Copyright (c) 2009-2013 [Nate Wiger](http://nateware.com). All Rights Reserved.
598
+ Copyright (c) 2009-2019 [Nate Wiger](http://nateware.com). All Rights Reserved.
556
599
  Released under the [Artistic License](http://www.opensource.org/licenses/artistic-license-2.0.php).
557
-
@@ -1,6 +1,12 @@
1
+ require 'redis/helpers/core_commands'
2
+
1
3
  class Redis
2
4
  # Defines base functionality for all redis-objects.
3
5
  class BaseObject
6
+ include Redis::Helpers::CoreCommands
7
+
8
+ attr_reader :key, :options
9
+
4
10
  def initialize(key, *args)
5
11
  @key = key.is_a?(Array) ? key.flatten.join(':') : key
6
12
  @options = args.last.is_a?(Hash) ? args.pop : {}
data/lib/redis/counter.rb CHANGED
@@ -9,10 +9,6 @@ class Redis
9
9
  # class to define a counter.
10
10
  #
11
11
  class Counter < BaseObject
12
- require 'redis/helpers/core_commands'
13
- include Redis::Helpers::CoreCommands
14
-
15
- attr_reader :key, :options
16
12
  def initialize(key, *args)
17
13
  super(key, *args)
18
14
  @options[:start] ||= @options[:default] || 0
@@ -106,7 +102,7 @@ class Redis
106
102
  def decrbyfloat(by=1.0, &block)
107
103
  allow_expiration do
108
104
  val = redis.incrbyfloat(key, -by).to_f
109
- block_given? ? rewindable_block(:incrbyfloat, -by, val, &block) : val
105
+ block_given? ? rewindable_block(:incrbyfloat, by, val, &block) : val
110
106
  end
111
107
  end
112
108
 
@@ -116,7 +112,7 @@ class Redis
116
112
  alias_method :to_i, :value
117
113
 
118
114
  def nil?
119
- !redis.exists(key)
115
+ !redis.exists?(key)
120
116
  end
121
117
 
122
118
  ##
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/base_object'
2
+
3
+ class Redis
4
+ #
5
+ # Class representing a Redis enumerable type (list, set, sorted set, or hash).
6
+ #
7
+ class EnumerableObject < BaseObject
8
+ include Enumerable
9
+
10
+ # Iterate through each member. Redis::Objects mixes in Enumerable,
11
+ # so you can also use familiar methods like +collect+, +detect+, and so forth.
12
+ def each(&block)
13
+ value.each(&block)
14
+ end
15
+
16
+ def sort(options={})
17
+ return super() if block_given?
18
+ options[:order] = "asc alpha" if options.keys.count == 0 # compat with Ruby
19
+ val = redis.sort(key, **options)
20
+ val.is_a?(Array) ? val.map{|v| unmarshal(v)} : val
21
+ end
22
+
23
+ # ActiveSupport's core extension `Enumerable#as_json` implementation is incompatible with ours.
24
+ def as_json(*)
25
+ to_hash
26
+ end
27
+ end
28
+ end
@@ -1,16 +1,10 @@
1
- require File.dirname(__FILE__) + '/base_object'
1
+ require File.dirname(__FILE__) + '/enumerable_object'
2
2
 
3
3
  class Redis
4
4
  #
5
5
  # Class representing a Redis hash.
6
6
  #
7
- class HashKey < BaseObject
8
- require 'enumerator'
9
- include Enumerable
10
- require 'redis/helpers/core_commands'
11
- include Redis::Helpers::CoreCommands
12
-
13
- attr_reader :key, :options
7
+ class HashKey < EnumerableObject
14
8
  def initialize(key, *args)
15
9
  super
16
10
  @options[:marshal_keys] ||= {}
@@ -74,11 +68,6 @@ class Redis
74
68
  alias_method :clone, :all
75
69
  alias_method :value, :all
76
70
 
77
- # Enumerate through all fields. Redis: HGETALL
78
- def each(&block)
79
- all.each(&block)
80
- end
81
-
82
71
  # Enumerate through each keys. Redis: HKEYS
83
72
  def each_key(&block)
84
73
  keys.each(&block)
@@ -101,11 +90,6 @@ class Redis
101
90
  true if size == 0
102
91
  end
103
92
 
104
- # Clears the dict of all keys/values. Redis: DEL
105
- def clear
106
- redis.del(key)
107
- end
108
-
109
93
  # Set keys in bulk, takes a hash of field/values {'field1' => 'val1'}. Redis: HMSET
110
94
  def bulk_set(*args)
111
95
  raise ArgumentError, "Argument to bulk_set must be hash of key/value pairs" unless args.last.is_a?(::Hash)
@@ -183,9 +167,5 @@ class Redis
183
167
  def decrbyfloat(field, by=1.0)
184
168
  incrbyfloat(field, -by)
185
169
  end
186
-
187
- def as_json(*)
188
- to_hash
189
- end
190
170
  end
191
171
  end
@@ -3,15 +3,16 @@ class Redis
3
3
  # These are core commands that all types share (rename, etc)
4
4
  module CoreCommands
5
5
  def exists?
6
- redis.exists key
6
+ redis.exists? key
7
7
  end
8
-
8
+
9
+ # Delete key. Redis: DEL
9
10
  def delete
10
11
  redis.del key
11
12
  end
12
13
  alias_method :del, :delete
13
14
  alias_method :clear, :delete
14
-
15
+
15
16
  def type
16
17
  redis.type key
17
18
  end
@@ -29,7 +30,7 @@ class Redis
29
30
  @key = dest if ret && setkey
30
31
  ret
31
32
  end
32
-
33
+
33
34
  def expire(seconds)
34
35
  redis.expire key, seconds
35
36
  end
@@ -50,20 +51,19 @@ class Redis
50
51
  redis.move key, dbindex
51
52
  end
52
53
 
53
- def sort(options={})
54
- options[:order] = "asc alpha" if options.keys.count == 0 # compat with Ruby
55
- val = redis.sort(key, options)
56
- val.is_a?(Array) ? val.map{|v| unmarshal(v)} : val
54
+ def serializer
55
+ options[:serializer] || Marshal
57
56
  end
58
57
 
59
58
  def marshal(value, domarshal=false)
60
59
  if options[:marshal] || domarshal
61
- Marshal.dump(value)
60
+ dump_args = options[:marshal_dump_args] || []
61
+ serializer.dump(value, *(dump_args.is_a?(Array) ? dump_args : [dump_args]))
62
62
  else
63
63
  value
64
64
  end
65
65
  end
66
-
66
+
67
67
  def unmarshal(value, domarshal=false)
68
68
  if value.nil?
69
69
  nil
@@ -73,7 +73,8 @@ class Redis
73
73
  elsif !value.is_a?(String)
74
74
  value
75
75
  else
76
- Marshal.load(value)
76
+ load_args = options[:marshal_load_args] || []
77
+ serializer.load(value, *(load_args.is_a?(Array) ? load_args : [load_args]))
77
78
  end
78
79
  else
79
80
  value
data/lib/redis/list.rb CHANGED
@@ -1,18 +1,11 @@
1
- require File.dirname(__FILE__) + '/base_object'
1
+ require File.dirname(__FILE__) + '/enumerable_object'
2
2
 
3
3
  class Redis
4
4
  #
5
5
  # Class representing a Redis list. Instances of Redis::List are designed to
6
6
  # behave as much like Ruby arrays as possible.
7
7
  #
8
- class List < BaseObject
9
- require 'enumerator'
10
- include Enumerable
11
- require 'redis/helpers/core_commands'
12
- include Redis::Helpers::CoreCommands
13
-
14
- attr_reader :key, :options
15
-
8
+ class List < EnumerableObject
16
9
  # Works like push. Can chain together: list << 'a' << 'b'
17
10
  def <<(value)
18
11
  push(value) # marshal in push()
@@ -29,8 +22,9 @@ class Redis
29
22
  # Add a member to the end of the list. Redis: RPUSH
30
23
  def push(*values)
31
24
  allow_expiration do
32
- redis.rpush(key, values.map{|v| marshal(v) })
25
+ count = redis.rpush(key, values.map{|v| marshal(v) })
33
26
  redis.ltrim(key, -options[:maxlength], -1) if options[:maxlength]
27
+ count
34
28
  end
35
29
  end
36
30
 
@@ -62,8 +56,9 @@ class Redis
62
56
  # Add a member to the start of the list. Redis: LPUSH
63
57
  def unshift(*values)
64
58
  allow_expiration do
65
- redis.lpush(key, values.map{|v| marshal(v) })
59
+ count = redis.lpush(key, values.map{|v| marshal(v) })
66
60
  redis.ltrim(key, 0, options[:maxlength] - 1) if options[:maxlength]
61
+ count
67
62
  end
68
63
  end
69
64
 
@@ -121,12 +116,6 @@ class Redis
121
116
  redis.lrem(key, count, marshal(name)) # weird api
122
117
  end
123
118
 
124
- # Iterate through each member of the set. Redis::Objects mixes in Enumerable,
125
- # so you can also use familiar methods like +collect+, +detect+, and so forth.
126
- def each(&block)
127
- values.each(&block)
128
- end
129
-
130
119
  # Return a range of values from +start_index+ to +end_index+. Can also use
131
120
  # the familiar list[start,end] Ruby syntax. Redis: LRANGE
132
121
  def range(start_index, end_index)
@@ -167,9 +156,5 @@ class Redis
167
156
  def to_s
168
157
  values.join(', ')
169
158
  end
170
-
171
- def as_json(*)
172
- to_hash
173
- end
174
159
  end
175
160
  end