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 +5 -5
- data/.travis.yml +2 -4
- data/CHANGELOG.rdoc +99 -0
- data/README.md +50 -8
- data/lib/redis/base_object.rb +6 -0
- data/lib/redis/counter.rb +2 -6
- data/lib/redis/enumerable_object.rb +28 -0
- data/lib/redis/hash_key.rb +2 -22
- data/lib/redis/helpers/core_commands.rb +12 -11
- data/lib/redis/list.rb +6 -21
- data/lib/redis/lock.rb +23 -28
- data/lib/redis/objects.rb +9 -4
- data/lib/redis/objects/connection_pool_proxy.rb +1 -0
- data/lib/redis/objects/hashes.rb +9 -0
- data/lib/redis/objects/lists.rb +9 -0
- data/lib/redis/objects/sets.rb +9 -0
- data/lib/redis/objects/version.rb +1 -1
- data/lib/redis/set.rb +5 -22
- data/lib/redis/sorted_set.rb +30 -41
- data/lib/redis/value.rb +25 -5
- data/spec/redis_objects_custom_serializer.rb +198 -0
- data/spec/redis_objects_instance_spec.rb +127 -36
- data/spec/redis_objects_model_spec.rb +32 -3
- metadata +11 -9
data/lib/redis/lock.rb
CHANGED
@@ -11,7 +11,6 @@ class Redis
|
|
11
11
|
class Lock < BaseObject
|
12
12
|
class LockTimeout < StandardError; end #:nodoc:
|
13
13
|
|
14
|
-
attr_reader :key, :options
|
15
14
|
def initialize(key, *args)
|
16
15
|
super(key, *args)
|
17
16
|
@options[:timeout] ||= 5
|
@@ -19,13 +18,6 @@ class Redis
|
|
19
18
|
redis.setnx(key, @options[:start]) unless @options[:start] == 0 || @options[:init] === false
|
20
19
|
end
|
21
20
|
|
22
|
-
# Clear the lock. Should only be needed if there's a server crash
|
23
|
-
# or some other event that gets locks in a stuck state.
|
24
|
-
def clear
|
25
|
-
redis.del(key)
|
26
|
-
end
|
27
|
-
alias_method :delete, :clear
|
28
|
-
|
29
21
|
def value
|
30
22
|
nil
|
31
23
|
end
|
@@ -33,28 +25,30 @@ class Redis
|
|
33
25
|
# Get the lock and execute the code block. Any other code that needs the lock
|
34
26
|
# (on any server) will spin waiting for the lock up to the :timeout
|
35
27
|
# that was specified when the lock was defined.
|
36
|
-
def lock
|
37
|
-
|
28
|
+
def lock
|
29
|
+
raise ArgumentError, 'Block not given' unless block_given?
|
30
|
+
expiration_ms = generate_expiration
|
31
|
+
expiration_s = expiration_ms / 1000.0
|
32
|
+
end_time = nil
|
38
33
|
try_until_timeout do
|
39
|
-
|
40
|
-
#
|
41
|
-
|
34
|
+
end_time = Time.now.to_i + expiration_s
|
35
|
+
# Set a NX record and use the Redis expiration mechanism.
|
36
|
+
# Empty value because the presence of it is enough to lock
|
37
|
+
# `px` only except an Integer in millisecond
|
38
|
+
break if redis.set(key, nil, px: expiration_ms, nx: true)
|
42
39
|
|
43
|
-
#
|
44
|
-
#
|
45
|
-
|
46
|
-
if !@options[:expiration].nil?
|
40
|
+
# Backward compatibility code
|
41
|
+
# TODO: remove at the next major release for performance
|
42
|
+
unless @options[:expiration].nil?
|
47
43
|
old_expiration = redis.get(key).to_f
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
# and we now have it.
|
57
|
-
break if old_expiration < Time.now.to_f
|
45
|
+
# Check it was not an empty string with `zero?` and
|
46
|
+
# the expiration time is passed.
|
47
|
+
if !old_expiration.zero? && old_expiration < Time.now.to_f
|
48
|
+
expiration_ms = generate_expiration
|
49
|
+
expiration_s = expiration_ms / 1000.0
|
50
|
+
end_time = Time.now.to_i + expiration_s
|
51
|
+
break if redis.set(key, nil, px: expiration_ms)
|
58
52
|
end
|
59
53
|
end
|
60
54
|
end
|
@@ -66,14 +60,15 @@ class Redis
|
|
66
60
|
# it's not safe for us to remove it. Check how much time has passed since we
|
67
61
|
# wrote the lock key and only delete it if it hasn't expired (or we're not using
|
68
62
|
# lock expiration)
|
69
|
-
if @options[:expiration].nil? ||
|
63
|
+
if @options[:expiration].nil? || end_time > Time.now.to_f
|
70
64
|
redis.del(key)
|
71
65
|
end
|
72
66
|
end
|
73
67
|
end
|
74
68
|
|
69
|
+
# Return expiration in milliseconds
|
75
70
|
def generate_expiration
|
76
|
-
@options[:expiration].nil? ? 1 :
|
71
|
+
((@options[:expiration].nil? ? 1 : @options[:expiration].to_f) * 1000).to_i
|
77
72
|
end
|
78
73
|
|
79
74
|
private
|
data/lib/redis/objects.rb
CHANGED
@@ -46,8 +46,6 @@ class Redis
|
|
46
46
|
#
|
47
47
|
#
|
48
48
|
module Objects
|
49
|
-
dir = File.expand_path(__FILE__.sub(/\.rb$/,''))
|
50
|
-
|
51
49
|
autoload :Counters, 'redis/objects/counters'
|
52
50
|
autoload :Lists, 'redis/objects/lists'
|
53
51
|
autoload :Locks, 'redis/objects/locks'
|
@@ -173,8 +171,15 @@ class Redis
|
|
173
171
|
def redis() self.class.redis end
|
174
172
|
def redis_objects() self.class.redis_objects end
|
175
173
|
|
176
|
-
def
|
177
|
-
redis.del(
|
174
|
+
def redis_delete_objects
|
175
|
+
redis.del(redis_instance_keys)
|
176
|
+
end
|
177
|
+
|
178
|
+
def redis_instance_keys
|
179
|
+
redis_objects
|
180
|
+
.reject { |_, value| value[:global] }
|
181
|
+
.keys
|
182
|
+
.collect { |name| redis_field_key(name) }
|
178
183
|
end
|
179
184
|
|
180
185
|
def redis_options(name) #:nodoc:
|
@@ -9,6 +9,7 @@ class Redis
|
|
9
9
|
def method_missing(name, *args, &block)
|
10
10
|
@pool.with { |x| x.send(name, *args, &block) }
|
11
11
|
end
|
12
|
+
ruby2_keywords :method_missing if respond_to?(:ruby2_keywords, true)
|
12
13
|
|
13
14
|
def respond_to_missing?(name, include_all = false)
|
14
15
|
@pool.with { |x| x.respond_to?(name, include_all) }
|
data/lib/redis/objects/hashes.rb
CHANGED
data/lib/redis/objects/lists.rb
CHANGED
data/lib/redis/objects/sets.rb
CHANGED
data/lib/redis/set.rb
CHANGED
@@ -1,17 +1,10 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/
|
1
|
+
require File.dirname(__FILE__) + '/enumerable_object'
|
2
2
|
|
3
3
|
class Redis
|
4
4
|
#
|
5
5
|
# Class representing a set.
|
6
6
|
#
|
7
|
-
class Set <
|
8
|
-
require 'enumerator'
|
9
|
-
include Enumerable
|
10
|
-
require 'redis/helpers/core_commands'
|
11
|
-
include Redis::Helpers::CoreCommands
|
12
|
-
|
13
|
-
attr_reader :key, :options
|
14
|
-
|
7
|
+
class Set < EnumerableObject
|
15
8
|
# Works like add. Can chain together: list << 'a' << 'b'
|
16
9
|
def <<(value)
|
17
10
|
add(value)
|
@@ -27,8 +20,8 @@ class Redis
|
|
27
20
|
end
|
28
21
|
|
29
22
|
# Remove and return a random member. Redis: SPOP
|
30
|
-
def pop
|
31
|
-
unmarshal redis.spop(key)
|
23
|
+
def pop(count = nil)
|
24
|
+
unmarshal redis.spop(key, count)
|
32
25
|
end
|
33
26
|
|
34
27
|
# return a random member. Redis: SRANDMEMBER
|
@@ -74,12 +67,6 @@ class Redis
|
|
74
67
|
res
|
75
68
|
end
|
76
69
|
|
77
|
-
# Iterate through each member of the set. Redis::Objects mixes in Enumerable,
|
78
|
-
# so you can also use familiar methods like +collect+, +detect+, and so forth.
|
79
|
-
def each(&block)
|
80
|
-
members.each(&block)
|
81
|
-
end
|
82
|
-
|
83
70
|
# Return the intersection with another set. Can pass it either another set
|
84
71
|
# object or set name. Also available as & which is a bit cleaner:
|
85
72
|
#
|
@@ -165,7 +152,7 @@ class Redis
|
|
165
152
|
redis.smove(key, destination.is_a?(Redis::Set) ? destination.key : destination.to_s, value)
|
166
153
|
end
|
167
154
|
|
168
|
-
# The number of members in the set. Aliased as size. Redis: SCARD
|
155
|
+
# The number of members in the set. Aliased as size or count. Redis: SCARD
|
169
156
|
def length
|
170
157
|
redis.scard(key)
|
171
158
|
end
|
@@ -185,10 +172,6 @@ class Redis
|
|
185
172
|
members.join(', ')
|
186
173
|
end
|
187
174
|
|
188
|
-
def as_json(*)
|
189
|
-
to_hash
|
190
|
-
end
|
191
|
-
|
192
175
|
private
|
193
176
|
|
194
177
|
def keys_from_objects(sets)
|
data/lib/redis/sorted_set.rb
CHANGED
@@ -1,17 +1,10 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/
|
1
|
+
require File.dirname(__FILE__) + '/enumerable_object'
|
2
2
|
|
3
3
|
class Redis
|
4
4
|
#
|
5
5
|
# Class representing a sorted set.
|
6
6
|
#
|
7
|
-
class SortedSet <
|
8
|
-
# require 'enumerator'
|
9
|
-
# include Enumerable
|
10
|
-
require 'redis/helpers/core_commands'
|
11
|
-
include Redis::Helpers::CoreCommands
|
12
|
-
|
13
|
-
attr_reader :key, :options
|
14
|
-
|
7
|
+
class SortedSet < EnumerableObject
|
15
8
|
# How to add values using a sorted set. The key is the member, eg,
|
16
9
|
# "Peter", and the value is the score, eg, 163. So:
|
17
10
|
# num_posts['Peter'] = 163
|
@@ -124,7 +117,7 @@ class Redis
|
|
124
117
|
options[:offset] || options[:limit] || options[:count]
|
125
118
|
args[:with_scores] = true if options[:withscores] || options[:with_scores]
|
126
119
|
|
127
|
-
redis.zrangebyscore(key, min, max, args).map{|v| unmarshal(v) }
|
120
|
+
redis.zrangebyscore(key, min, max, **args).map{|v| unmarshal(v) }
|
128
121
|
end
|
129
122
|
|
130
123
|
# Returns all the elements in the sorted set at key with a score between max and min
|
@@ -140,7 +133,7 @@ class Redis
|
|
140
133
|
options[:offset] || options[:limit] || options[:count]
|
141
134
|
args[:with_scores] = true if options[:withscores] || options[:with_scores]
|
142
135
|
|
143
|
-
redis.zrevrangebyscore(key, max, min, args).map{|v| unmarshal(v) }
|
136
|
+
redis.zrevrangebyscore(key, max, min, **args).map{|v| unmarshal(v) }
|
144
137
|
end
|
145
138
|
|
146
139
|
# Remove all elements in the sorted set at key with rank between start and end. Start and end are
|
@@ -208,7 +201,17 @@ class Redis
|
|
208
201
|
#
|
209
202
|
# Redis: SINTER
|
210
203
|
def intersection(*sets)
|
211
|
-
|
204
|
+
result = nil
|
205
|
+
temp_key = :"#{key}:intersection:#{Time.current.to_i + rand}"
|
206
|
+
|
207
|
+
redis.multi do
|
208
|
+
interstore(temp_key, *sets)
|
209
|
+
redis.expire(temp_key, 1)
|
210
|
+
|
211
|
+
result = redis.zrange(temp_key, 0, -1)
|
212
|
+
end
|
213
|
+
|
214
|
+
result.value
|
212
215
|
end
|
213
216
|
alias_method :intersect, :intersection
|
214
217
|
alias_method :inter, :intersection
|
@@ -219,7 +222,7 @@ class Redis
|
|
219
222
|
def interstore(name, *sets)
|
220
223
|
allow_expiration do
|
221
224
|
opts = sets.last.is_a?(Hash) ? sets.pop : {}
|
222
|
-
redis.zinterstore(key_from_object(name), keys_from_objects([self] + sets), opts)
|
225
|
+
redis.zinterstore(key_from_object(name), keys_from_objects([self] + sets), **opts)
|
223
226
|
end
|
224
227
|
end
|
225
228
|
|
@@ -235,7 +238,17 @@ class Redis
|
|
235
238
|
#
|
236
239
|
# Redis: SUNION
|
237
240
|
def union(*sets)
|
238
|
-
|
241
|
+
result = nil
|
242
|
+
temp_key = :"#{key}:union:#{Time.current.to_i + rand}"
|
243
|
+
|
244
|
+
redis.multi do
|
245
|
+
unionstore(temp_key, *sets)
|
246
|
+
redis.expire(temp_key, 1)
|
247
|
+
|
248
|
+
result = redis.zrange(temp_key, 0, -1)
|
249
|
+
end
|
250
|
+
|
251
|
+
result.value
|
239
252
|
end
|
240
253
|
alias_method :|, :union
|
241
254
|
alias_method :+, :union
|
@@ -245,35 +258,10 @@ class Redis
|
|
245
258
|
def unionstore(name, *sets)
|
246
259
|
allow_expiration do
|
247
260
|
opts = sets.last.is_a?(Hash) ? sets.pop : {}
|
248
|
-
redis.zunionstore(key_from_object(name), keys_from_objects([self] + sets), opts)
|
261
|
+
redis.zunionstore(key_from_object(name), keys_from_objects([self] + sets), **opts)
|
249
262
|
end
|
250
263
|
end
|
251
264
|
|
252
|
-
# Return the difference vs another set. Can pass it either another set
|
253
|
-
# object or set name. Also available as ^ or - which is a bit cleaner:
|
254
|
-
#
|
255
|
-
# members_difference = set1 ^ set2
|
256
|
-
# members_difference = set1 - set2
|
257
|
-
#
|
258
|
-
# If you want to specify multiple sets, you must use +difference+:
|
259
|
-
#
|
260
|
-
# members_difference = set1.difference(set2, set3, set4)
|
261
|
-
# members_difference = set1.diff(set2, set3, set4)
|
262
|
-
#
|
263
|
-
# Redis: SDIFF
|
264
|
-
def difference(*sets)
|
265
|
-
redis.zdiff(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
|
266
|
-
end
|
267
|
-
alias_method :diff, :difference
|
268
|
-
alias_method :^, :difference
|
269
|
-
alias_method :-, :difference
|
270
|
-
|
271
|
-
# Calculate the diff and store it in Redis as +name+. Returns the number
|
272
|
-
# of elements in the stored union. Redis: SDIFFSTORE
|
273
|
-
def diffstore(name, *sets)
|
274
|
-
redis.zdiffstore(name, key, *keys_from_objects(sets))
|
275
|
-
end
|
276
|
-
|
277
265
|
# Returns true if the set has no members. Redis: SCARD == 0
|
278
266
|
def empty?
|
279
267
|
length == 0
|
@@ -303,11 +291,12 @@ class Redis
|
|
303
291
|
at(-1)
|
304
292
|
end
|
305
293
|
|
306
|
-
# The number of members in the set. Aliased as size. Redis: ZCARD
|
294
|
+
# The number of members in the set. Aliased as size or count. Redis: ZCARD
|
307
295
|
def length
|
308
296
|
redis.zcard(key)
|
309
297
|
end
|
310
298
|
alias_method :size, :length
|
299
|
+
alias_method :count, :length
|
311
300
|
|
312
301
|
# The number of members within a range of scores. Redis: ZCOUNT
|
313
302
|
def range_size(min, max)
|
data/lib/redis/value.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/base_object'
|
2
|
+
require 'zlib'
|
2
3
|
|
3
4
|
class Redis
|
4
5
|
#
|
5
6
|
# Class representing a simple value. You can use standard Ruby operations on it.
|
6
7
|
#
|
7
8
|
class Value < BaseObject
|
8
|
-
require 'redis/helpers/core_commands'
|
9
|
-
include Redis::Helpers::CoreCommands
|
10
|
-
|
11
|
-
attr_reader :key, :options
|
12
|
-
|
13
9
|
def value=(val)
|
14
10
|
allow_expiration do
|
15
11
|
if val.nil?
|
@@ -31,6 +27,30 @@ class Redis
|
|
31
27
|
end
|
32
28
|
alias_method :get, :value
|
33
29
|
|
30
|
+
def marshal(value, *args)
|
31
|
+
if !value.nil? && options[:compress]
|
32
|
+
compress(super)
|
33
|
+
else
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def unmarshal(value, *args)
|
39
|
+
if !value.nil? && options[:compress]
|
40
|
+
super(decompress(value), *args)
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def decompress(value)
|
47
|
+
Zlib::Inflate.inflate(value)
|
48
|
+
end
|
49
|
+
|
50
|
+
def compress(value)
|
51
|
+
Zlib::Deflate.deflate(value)
|
52
|
+
end
|
53
|
+
|
34
54
|
def inspect
|
35
55
|
"#<Redis::Value #{value.inspect}>"
|
36
56
|
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
require 'redis/objects'
|
5
|
+
|
6
|
+
class CustomSerializer
|
7
|
+
class << self
|
8
|
+
attr_accessor :dump_called, :load_called, :dump_args, :load_args
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.dump(value, *args, **kargs)
|
12
|
+
@dump_called = true
|
13
|
+
@dump_args = [args, kargs]
|
14
|
+
Marshal.dump(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.load(value, *args, **kargs)
|
18
|
+
@load_called = true
|
19
|
+
@load_args = [args, kargs]
|
20
|
+
Marshal.load(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.reset!
|
24
|
+
@dump_called = nil
|
25
|
+
@load_called = nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'with custom serialization' do
|
30
|
+
before do
|
31
|
+
CustomSerializer.reset!
|
32
|
+
end
|
33
|
+
|
34
|
+
describe Redis::Value do
|
35
|
+
before do
|
36
|
+
@value = Redis::Value.new(
|
37
|
+
'spec/value_custom_serializer',
|
38
|
+
marshal: true,
|
39
|
+
serializer: CustomSerializer
|
40
|
+
)
|
41
|
+
@value.clear
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'uses custom serializer' do
|
45
|
+
@value.value = { json: 'data' }
|
46
|
+
CustomSerializer.dump_called.should == true
|
47
|
+
CustomSerializer.load_called.should == nil
|
48
|
+
@value.value.should == { json: 'data' }
|
49
|
+
CustomSerializer.dump_called.should == true
|
50
|
+
CustomSerializer.load_called.should == true
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'passes extra arguments to dump' do
|
54
|
+
@value.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
55
|
+
@value.value = 1
|
56
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'passes extra arguments to load' do
|
60
|
+
@value.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
61
|
+
@value.value = 1
|
62
|
+
@value.value.should == 1
|
63
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe Redis::List do
|
68
|
+
before do
|
69
|
+
@list = Redis::List.new(
|
70
|
+
'spec/list_custom_serializer',
|
71
|
+
marshal: true,
|
72
|
+
serializer: CustomSerializer
|
73
|
+
)
|
74
|
+
@list.clear
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'uses custom serializer' do
|
78
|
+
@list << { json: 'data' }
|
79
|
+
CustomSerializer.dump_called.should == true
|
80
|
+
CustomSerializer.load_called.should == nil
|
81
|
+
@list.should == [{ json: 'data' }]
|
82
|
+
CustomSerializer.dump_called.should == true
|
83
|
+
CustomSerializer.load_called.should == true
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'passes extra arguments to dump' do
|
87
|
+
@list.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
88
|
+
@list << 1
|
89
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'passes extra arguments to load' do
|
93
|
+
@list.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
94
|
+
@list << 1
|
95
|
+
@list.values.should == [1]
|
96
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe Redis::HashKey do
|
101
|
+
before do
|
102
|
+
@hash = Redis::HashKey.new(
|
103
|
+
'spec/hash_custom_serializer',
|
104
|
+
marshal: true,
|
105
|
+
serializer: CustomSerializer
|
106
|
+
)
|
107
|
+
@hash.clear
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'uses custom serializer' do
|
111
|
+
@hash['a'] = 1
|
112
|
+
CustomSerializer.dump_called.should == true
|
113
|
+
CustomSerializer.load_called.should == nil
|
114
|
+
@hash.value.should == { 'a' => 1 }
|
115
|
+
CustomSerializer.dump_called.should == true
|
116
|
+
CustomSerializer.load_called.should == true
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'passes extra arguments to dump' do
|
120
|
+
@hash.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
121
|
+
@hash['a'] = 1
|
122
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'passes extra arguments to load' do
|
126
|
+
@hash.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
127
|
+
@hash['a'] = 1
|
128
|
+
@hash.value.should == { 'a' => 1 }
|
129
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe Redis::Set do
|
134
|
+
before do
|
135
|
+
@set = Redis::Set.new(
|
136
|
+
'spec/set_custom_serializer',
|
137
|
+
marshal: true,
|
138
|
+
serializer: CustomSerializer
|
139
|
+
)
|
140
|
+
@set.clear
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'uses custom serializer' do
|
144
|
+
@set << 'a'
|
145
|
+
CustomSerializer.dump_called.should == true
|
146
|
+
CustomSerializer.load_called.should == nil
|
147
|
+
@set.members.should == ['a']
|
148
|
+
CustomSerializer.dump_called.should == true
|
149
|
+
CustomSerializer.load_called.should == true
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'passes extra arguments to dump' do
|
153
|
+
@set.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
154
|
+
@set << 'a'
|
155
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'passes extra arguments to load' do
|
159
|
+
@set.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
160
|
+
@set << 'a'
|
161
|
+
@set.members.should == ['a']
|
162
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe Redis::SortedSet do
|
167
|
+
before do
|
168
|
+
@set = Redis::SortedSet.new(
|
169
|
+
'spec/zset_custom_serializer',
|
170
|
+
marshal: true,
|
171
|
+
serializer: CustomSerializer
|
172
|
+
)
|
173
|
+
@set.clear
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'uses custom serializer' do
|
177
|
+
@set['a'] = 1
|
178
|
+
CustomSerializer.dump_called.should == true
|
179
|
+
CustomSerializer.load_called.should == nil
|
180
|
+
@set.members.should == ['a']
|
181
|
+
CustomSerializer.dump_called.should == true
|
182
|
+
CustomSerializer.load_called.should == true
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'passes extra arguments to dump' do
|
186
|
+
@set.options[:marshal_dump_args] = ['some', { extra: 'arguments' }]
|
187
|
+
@set['a'] = 1
|
188
|
+
CustomSerializer.dump_args.should == [['some'], { extra: 'arguments' }]
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'passes extra arguments to load' do
|
192
|
+
@set.options[:marshal_load_args] = ['some', { extra: 'arguments' }]
|
193
|
+
@set['a'] = 1
|
194
|
+
@set.members.should == ['a']
|
195
|
+
CustomSerializer.load_args.should == [['some'], { extra: 'arguments' }]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|