redis-objects 0.8.0 → 0.9.1
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/CHANGELOG.rdoc +31 -3
- data/README.md +7 -0
- data/lib/redis/base_object.rb +32 -0
- data/lib/redis/counter.rb +34 -1
- data/lib/redis/hash_key.rb +46 -28
- data/lib/redis/helpers/core_commands.rb +20 -2
- data/lib/redis/list.rb +15 -15
- data/lib/redis/objects/counters.rb +1 -1
- data/lib/redis/objects/hashes.rb +1 -1
- data/lib/redis/objects/lists.rb +1 -1
- data/lib/redis/objects/locks.rb +2 -2
- data/lib/redis/objects/sets.rb +1 -1
- data/lib/redis/objects/sorted_sets.rb +1 -1
- data/lib/redis/objects/values.rb +1 -1
- data/lib/redis/objects/version.rb +1 -1
- data/lib/redis/objects.rb +11 -1
- data/lib/redis/set.rb +25 -20
- data/lib/redis/sorted_set.rb +31 -22
- data/lib/redis/value.rb +5 -5
- data/spec/redis_objects_conn_spec.rb +32 -2
- data/spec/redis_objects_instance_spec.rb +195 -2
- data/spec/redis_objects_model_spec.rb +70 -4
- data/spec/spec_helper.rb +21 -16
- metadata +19 -20
- data/lib/redis/helpers/serialize.rb +0 -41
data/lib/redis/set.rb
CHANGED
|
@@ -9,8 +9,6 @@ class Redis
|
|
|
9
9
|
include Enumerable
|
|
10
10
|
require 'redis/helpers/core_commands'
|
|
11
11
|
include Redis::Helpers::CoreCommands
|
|
12
|
-
require 'redis/helpers/serialize'
|
|
13
|
-
include Redis::Helpers::Serialize
|
|
14
12
|
|
|
15
13
|
attr_reader :key, :options
|
|
16
14
|
|
|
@@ -23,49 +21,54 @@ class Redis
|
|
|
23
21
|
# Add the specified value to the set only if it does not exist already.
|
|
24
22
|
# Redis: SADD
|
|
25
23
|
def add(value)
|
|
26
|
-
redis.sadd(key,
|
|
24
|
+
redis.sadd(key, marshal(value)) if value.nil? || !Array(value).empty?
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
# Remove and return a random member. Redis: SPOP
|
|
30
28
|
def pop
|
|
31
|
-
|
|
29
|
+
unmarshal redis.spop(key)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# return a random member. Redis: SRANDMEMBER
|
|
33
|
+
def randmember
|
|
34
|
+
unmarshal redis.srandmember(key)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
# Adds the specified values to the set. Only works on redis > 2.4
|
|
35
38
|
# Redis: SADD
|
|
36
39
|
def merge(*values)
|
|
37
|
-
redis.sadd(key, values.flatten.map{|v|
|
|
40
|
+
redis.sadd(key, values.flatten.map{|v| marshal(v)})
|
|
38
41
|
end
|
|
39
42
|
|
|
40
43
|
# Return all members in the set. Redis: SMEMBERS
|
|
41
44
|
def members
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
vals = redis.smembers(key)
|
|
46
|
+
vals.nil? ? [] : vals.map{|v| unmarshal(v) }
|
|
44
47
|
end
|
|
45
48
|
alias_method :get, :members
|
|
46
49
|
|
|
47
50
|
# Returns true if the specified value is in the set. Redis: SISMEMBER
|
|
48
51
|
def member?(value)
|
|
49
|
-
redis.sismember(key,
|
|
52
|
+
redis.sismember(key, marshal(value))
|
|
50
53
|
end
|
|
51
54
|
alias_method :include?, :member?
|
|
52
|
-
|
|
55
|
+
|
|
53
56
|
# Delete the value from the set. Redis: SREM
|
|
54
57
|
def delete(value)
|
|
55
|
-
redis.srem(key,
|
|
58
|
+
redis.srem(key, marshal(value))
|
|
56
59
|
end
|
|
57
|
-
|
|
60
|
+
|
|
58
61
|
# Delete if matches block
|
|
59
62
|
def delete_if(&block)
|
|
60
63
|
res = false
|
|
61
64
|
redis.smembers(key).each do |m|
|
|
62
|
-
if block.call(
|
|
65
|
+
if block.call(unmarshal(m))
|
|
63
66
|
res = redis.srem(key, m)
|
|
64
67
|
end
|
|
65
68
|
end
|
|
66
69
|
res
|
|
67
70
|
end
|
|
68
|
-
|
|
71
|
+
|
|
69
72
|
# Iterate through each member of the set. Redis::Objects mixes in Enumerable,
|
|
70
73
|
# so you can also use familiar methods like +collect+, +detect+, and so forth.
|
|
71
74
|
def each(&block)
|
|
@@ -84,12 +87,12 @@ class Redis
|
|
|
84
87
|
#
|
|
85
88
|
# Redis: SINTER
|
|
86
89
|
def intersection(*sets)
|
|
87
|
-
|
|
90
|
+
redis.sinter(key, *keys_from_objects(sets)).map{|v| unmarshal(v)}
|
|
88
91
|
end
|
|
89
92
|
alias_method :intersect, :intersection
|
|
90
93
|
alias_method :inter, :intersection
|
|
91
94
|
alias_method :&, :intersection
|
|
92
|
-
|
|
95
|
+
|
|
93
96
|
# Calculate the intersection and store it in Redis as +name+. Returns the number
|
|
94
97
|
# of elements in the stored intersection. Redis: SUNIONSTORE
|
|
95
98
|
def interstore(name, *sets)
|
|
@@ -108,7 +111,7 @@ class Redis
|
|
|
108
111
|
#
|
|
109
112
|
# Redis: SUNION
|
|
110
113
|
def union(*sets)
|
|
111
|
-
|
|
114
|
+
redis.sunion(key, *keys_from_objects(sets)).map{|v| unmarshal(v)}
|
|
112
115
|
end
|
|
113
116
|
alias_method :|, :union
|
|
114
117
|
alias_method :+, :union
|
|
@@ -132,7 +135,7 @@ class Redis
|
|
|
132
135
|
#
|
|
133
136
|
# Redis: SDIFF
|
|
134
137
|
def difference(*sets)
|
|
135
|
-
|
|
138
|
+
redis.sdiff(key, *keys_from_objects(sets)).map{|v| unmarshal(v)}
|
|
136
139
|
end
|
|
137
140
|
alias_method :diff, :difference
|
|
138
141
|
alias_method :^, :difference
|
|
@@ -172,17 +175,19 @@ class Redis
|
|
|
172
175
|
def ==(x)
|
|
173
176
|
members == x
|
|
174
177
|
end
|
|
175
|
-
|
|
178
|
+
|
|
176
179
|
def to_s
|
|
177
180
|
members.join(', ')
|
|
178
181
|
end
|
|
179
182
|
|
|
183
|
+
expiration_filter :add
|
|
184
|
+
|
|
180
185
|
private
|
|
181
|
-
|
|
186
|
+
|
|
182
187
|
def keys_from_objects(sets)
|
|
183
188
|
raise ArgumentError, "Must pass in one or more set names" if sets.empty?
|
|
184
189
|
sets.collect{|set| set.is_a?(Redis::Set) ? set.key : set}
|
|
185
190
|
end
|
|
186
|
-
|
|
191
|
+
|
|
187
192
|
end
|
|
188
193
|
end
|
data/lib/redis/sorted_set.rb
CHANGED
|
@@ -9,8 +9,6 @@ class Redis
|
|
|
9
9
|
# include Enumerable
|
|
10
10
|
require 'redis/helpers/core_commands'
|
|
11
11
|
include Redis::Helpers::CoreCommands
|
|
12
|
-
require 'redis/helpers/serialize'
|
|
13
|
-
include Redis::Helpers::Serialize
|
|
14
12
|
|
|
15
13
|
attr_reader :key, :options
|
|
16
14
|
|
|
@@ -25,9 +23,19 @@ class Redis
|
|
|
25
23
|
# arguments to this are flipped; the member comes first rather than
|
|
26
24
|
# the score, since the member is the unique item (not the score).
|
|
27
25
|
def add(member, score)
|
|
28
|
-
redis.zadd(key, score,
|
|
26
|
+
redis.zadd(key, score, marshal(member))
|
|
29
27
|
end
|
|
30
28
|
|
|
29
|
+
# Add a list of members and their corresponding value (or a hash mapping
|
|
30
|
+
# values to scores) to Redis. Note that the arguments to this are flipped;
|
|
31
|
+
# the member comes first rather than the score, since the member is the unique
|
|
32
|
+
# item (not the score).
|
|
33
|
+
def merge(values)
|
|
34
|
+
vals = values.map{|v,s| [s, marshal(v)] }
|
|
35
|
+
redis.zadd(key, vals)
|
|
36
|
+
end
|
|
37
|
+
alias_method :add_all, :merge
|
|
38
|
+
|
|
31
39
|
# Same functionality as Ruby arrays. If a single number is given, return
|
|
32
40
|
# just the element at that index using Redis: ZRANGE. Otherwise, return
|
|
33
41
|
# a range of values using Redis: ZRANGE.
|
|
@@ -50,7 +58,7 @@ class Redis
|
|
|
50
58
|
# specified element does not exist in the sorted set, or the key does not exist
|
|
51
59
|
# at all, nil is returned. Redis: ZSCORE.
|
|
52
60
|
def score(member)
|
|
53
|
-
result = redis.zscore(key,
|
|
61
|
+
result = redis.zscore(key, marshal(member))
|
|
54
62
|
|
|
55
63
|
result.to_f unless result.nil?
|
|
56
64
|
end
|
|
@@ -60,7 +68,7 @@ class Redis
|
|
|
60
68
|
# When the given member does not exist in the sorted set, nil is returned.
|
|
61
69
|
# The returned rank (or index) of the member is 0-based for both commands
|
|
62
70
|
def rank(member)
|
|
63
|
-
if n = redis.zrank(key,
|
|
71
|
+
if n = redis.zrank(key, marshal(member))
|
|
64
72
|
n.to_i
|
|
65
73
|
else
|
|
66
74
|
nil
|
|
@@ -68,7 +76,7 @@ class Redis
|
|
|
68
76
|
end
|
|
69
77
|
|
|
70
78
|
def revrank(member)
|
|
71
|
-
if n = redis.zrevrank(key,
|
|
79
|
+
if n = redis.zrevrank(key, marshal(member))
|
|
72
80
|
n.to_i
|
|
73
81
|
else
|
|
74
82
|
nil
|
|
@@ -78,26 +86,25 @@ class Redis
|
|
|
78
86
|
# Return all members of the sorted set with their scores. Extremely CPU-intensive.
|
|
79
87
|
# Better to use a range instead.
|
|
80
88
|
def members(options={})
|
|
81
|
-
|
|
82
|
-
v.nil? ? [] : v
|
|
89
|
+
range(0, -1, options) || []
|
|
83
90
|
end
|
|
84
91
|
|
|
85
92
|
# Return a range of values from +start_index+ to +end_index+. Can also use
|
|
86
93
|
# the familiar list[start,end] Ruby syntax. Redis: ZRANGE
|
|
87
94
|
def range(start_index, end_index, options={})
|
|
88
95
|
if options[:withscores] || options[:with_scores]
|
|
89
|
-
|
|
96
|
+
redis.zrange(key, start_index, end_index, :with_scores => true).map{|v,s| [unmarshal(v), s] }
|
|
90
97
|
else
|
|
91
|
-
|
|
98
|
+
redis.zrange(key, start_index, end_index).map{|v| unmarshal(v) }
|
|
92
99
|
end
|
|
93
100
|
end
|
|
94
101
|
|
|
95
102
|
# Return a range of values from +start_index+ to +end_index+ in reverse order. Redis: ZREVRANGE
|
|
96
103
|
def revrange(start_index, end_index, options={})
|
|
97
104
|
if options[:withscores] || options[:with_scores]
|
|
98
|
-
|
|
105
|
+
redis.zrevrange(key, start_index, end_index, :with_scores => true).map{|v,s| [unmarshal(v), s] }
|
|
99
106
|
else
|
|
100
|
-
|
|
107
|
+
redis.zrevrange(key, start_index, end_index).map{|v| unmarshal(v) }
|
|
101
108
|
end
|
|
102
109
|
end
|
|
103
110
|
|
|
@@ -112,7 +119,7 @@ class Redis
|
|
|
112
119
|
options[:offset] || options[:limit] || options[:count]
|
|
113
120
|
args[:with_scores] = true if options[:withscores] || options[:with_scores]
|
|
114
121
|
|
|
115
|
-
|
|
122
|
+
redis.zrangebyscore(key, min, max, args).map{|v| unmarshal(v) }
|
|
116
123
|
end
|
|
117
124
|
|
|
118
125
|
# Returns all the elements in the sorted set at key with a score between max and min
|
|
@@ -128,7 +135,7 @@ class Redis
|
|
|
128
135
|
options[:offset] || options[:limit] || options[:count]
|
|
129
136
|
args[:with_scores] = true if options[:withscores] || options[:with_scores]
|
|
130
137
|
|
|
131
|
-
|
|
138
|
+
redis.zrevrangebyscore(key, max, min, args).map{|v| unmarshal(v) }
|
|
132
139
|
end
|
|
133
140
|
|
|
134
141
|
# Remove all elements in the sorted set at key with rank between start and end. Start and end are
|
|
@@ -148,7 +155,7 @@ class Redis
|
|
|
148
155
|
|
|
149
156
|
# Delete the value from the set. Redis: ZREM
|
|
150
157
|
def delete(value)
|
|
151
|
-
redis.zrem(key,
|
|
158
|
+
redis.zrem(key, marshal(value))
|
|
152
159
|
end
|
|
153
160
|
|
|
154
161
|
# Delete element if it matches block
|
|
@@ -156,7 +163,7 @@ class Redis
|
|
|
156
163
|
raise ArgumentError, "Missing block to SortedSet#delete_if" unless block_given?
|
|
157
164
|
res = false
|
|
158
165
|
redis.zrange(key, 0, -1).each do |m|
|
|
159
|
-
if block.call(
|
|
166
|
+
if block.call(unmarshal(m))
|
|
160
167
|
res = redis.zrem(key, m)
|
|
161
168
|
end
|
|
162
169
|
end
|
|
@@ -166,14 +173,14 @@ class Redis
|
|
|
166
173
|
# Increment the rank of that member atomically and return the new value. This
|
|
167
174
|
# method is aliased as incr() for brevity. Redis: ZINCRBY
|
|
168
175
|
def increment(member, by=1)
|
|
169
|
-
redis.zincrby(key, by,
|
|
176
|
+
redis.zincrby(key, by, marshal(member)).to_i
|
|
170
177
|
end
|
|
171
178
|
alias_method :incr, :increment
|
|
172
179
|
alias_method :incrby, :increment
|
|
173
180
|
|
|
174
181
|
# Convenience to calling increment() with a negative number.
|
|
175
182
|
def decrement(member, by=1)
|
|
176
|
-
redis.zincrby(key, -by,
|
|
183
|
+
redis.zincrby(key, -by, marshal(member)).to_i
|
|
177
184
|
end
|
|
178
185
|
alias_method :decr, :decrement
|
|
179
186
|
alias_method :decrby, :decrement
|
|
@@ -190,7 +197,7 @@ class Redis
|
|
|
190
197
|
#
|
|
191
198
|
# Redis: SINTER
|
|
192
199
|
def intersection(*sets)
|
|
193
|
-
|
|
200
|
+
redis.zinter(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
|
|
194
201
|
end
|
|
195
202
|
alias_method :intersect, :intersection
|
|
196
203
|
alias_method :inter, :intersection
|
|
@@ -214,7 +221,7 @@ class Redis
|
|
|
214
221
|
#
|
|
215
222
|
# Redis: SUNION
|
|
216
223
|
def union(*sets)
|
|
217
|
-
|
|
224
|
+
redis.zunion(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
|
|
218
225
|
end
|
|
219
226
|
alias_method :|, :union
|
|
220
227
|
alias_method :+, :union
|
|
@@ -238,7 +245,7 @@ class Redis
|
|
|
238
245
|
#
|
|
239
246
|
# Redis: SDIFF
|
|
240
247
|
def difference(*sets)
|
|
241
|
-
|
|
248
|
+
redis.zdiff(key, *keys_from_objects(sets)).map{|v| unmarshal(v) }
|
|
242
249
|
end
|
|
243
250
|
alias_method :diff, :difference
|
|
244
251
|
alias_method :^, :difference
|
|
@@ -292,9 +299,11 @@ class Redis
|
|
|
292
299
|
|
|
293
300
|
# Return a boolean indicating whether +value+ is a member.
|
|
294
301
|
def member?(value)
|
|
295
|
-
!redis.zscore(key,
|
|
302
|
+
!redis.zscore(key, marshal(value)).nil?
|
|
296
303
|
end
|
|
297
304
|
|
|
305
|
+
expiration_filter :[]=, :add, :merge, :diffstore, :increment, :decrement, :intersection, :interstore, :unionstore
|
|
306
|
+
|
|
298
307
|
private
|
|
299
308
|
|
|
300
309
|
def keys_from_objects(sets)
|
data/lib/redis/value.rb
CHANGED
|
@@ -7,26 +7,24 @@ class Redis
|
|
|
7
7
|
class Value < BaseObject
|
|
8
8
|
require 'redis/helpers/core_commands'
|
|
9
9
|
include Redis::Helpers::CoreCommands
|
|
10
|
-
require 'redis/helpers/serialize'
|
|
11
|
-
include Redis::Helpers::Serialize
|
|
12
10
|
|
|
13
11
|
attr_reader :key, :options
|
|
14
12
|
def initialize(key, *args)
|
|
15
13
|
super(key, *args)
|
|
16
|
-
redis.setnx(key,
|
|
14
|
+
redis.setnx(key, marshal(@options[:default])) if @options[:default]
|
|
17
15
|
end
|
|
18
16
|
|
|
19
17
|
def value=(val)
|
|
20
18
|
if val.nil?
|
|
21
19
|
delete
|
|
22
20
|
else
|
|
23
|
-
redis.set key,
|
|
21
|
+
redis.set key, marshal(val)
|
|
24
22
|
end
|
|
25
23
|
end
|
|
26
24
|
alias_method :set, :value=
|
|
27
25
|
|
|
28
26
|
def value
|
|
29
|
-
|
|
27
|
+
unmarshal redis.get(key)
|
|
30
28
|
end
|
|
31
29
|
alias_method :get, :value
|
|
32
30
|
|
|
@@ -42,5 +40,7 @@ class Redis
|
|
|
42
40
|
def method_missing(*args)
|
|
43
41
|
self.value.send *args
|
|
44
42
|
end
|
|
43
|
+
|
|
44
|
+
expiration_filter :value=
|
|
45
45
|
end
|
|
46
46
|
end
|
|
@@ -9,6 +9,38 @@ BAD_REDIS = "totally bad bogus redis handle"
|
|
|
9
9
|
|
|
10
10
|
# Grab a global handle
|
|
11
11
|
describe 'Connection tests' do
|
|
12
|
+
it "should support overriding object handles" do
|
|
13
|
+
|
|
14
|
+
class CustomConnectionObject
|
|
15
|
+
include Redis::Objects
|
|
16
|
+
|
|
17
|
+
def id
|
|
18
|
+
return 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
redis_handle = Redis.new(:host => REDIS_HOST, :port => REDIS_PORT, :db => 31)
|
|
22
|
+
value :redis_value, :redis => redis_handle, :key => 'rval'
|
|
23
|
+
value :default_redis_value, :key => 'rval'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
obj = CustomConnectionObject.new
|
|
27
|
+
|
|
28
|
+
obj.default_redis_value.value.should == nil
|
|
29
|
+
obj.redis_value.value.should == nil
|
|
30
|
+
|
|
31
|
+
obj.default_redis_value.value = 'foo'
|
|
32
|
+
obj.default_redis_value.value.should == 'foo'
|
|
33
|
+
obj.redis_value.value.should == nil
|
|
34
|
+
|
|
35
|
+
obj.default_redis_value.clear
|
|
36
|
+
obj.redis_value.value = 'foo'
|
|
37
|
+
obj.redis_value.value.should == 'foo'
|
|
38
|
+
obj.default_redis_value.value.should == nil
|
|
39
|
+
|
|
40
|
+
obj.redis_value.clear
|
|
41
|
+
obj.default_redis_value.clear
|
|
42
|
+
end
|
|
43
|
+
|
|
12
44
|
it "should support local handles" do
|
|
13
45
|
Redis.current = nil # reset from other tests
|
|
14
46
|
Redis::Objects.redis = nil
|
|
@@ -100,5 +132,3 @@ describe 'Connection tests' do
|
|
|
100
132
|
end
|
|
101
133
|
|
|
102
134
|
end
|
|
103
|
-
|
|
104
|
-
|
|
@@ -46,6 +46,24 @@ describe Redis::Value do
|
|
|
46
46
|
@value.options[:marshal] = false
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
it "should not erroneously unmarshall a string" do
|
|
50
|
+
json_string = {json: 'value'}
|
|
51
|
+
@value = Redis::Value.new('spec/value', :marshal => true)
|
|
52
|
+
@value.value = json_string
|
|
53
|
+
@value.value.should == json_string
|
|
54
|
+
@value.clear
|
|
55
|
+
|
|
56
|
+
default_json_string = {json: 'default'}
|
|
57
|
+
@value = Redis::Value.new('spec/default', :default => default_json_string, :marshal => true)
|
|
58
|
+
@value.value.should == default_json_string
|
|
59
|
+
@value.clear
|
|
60
|
+
|
|
61
|
+
marshalled_string = Marshal.dump({json: 'marshal'})
|
|
62
|
+
@value = Redis::Value.new('spec/marshal', :default => marshalled_string, :marshal => true)
|
|
63
|
+
@value.value.should == marshalled_string
|
|
64
|
+
@value.clear
|
|
65
|
+
end
|
|
66
|
+
|
|
49
67
|
it "should support renaming values" do
|
|
50
68
|
@value.value = 'Peter Pan'
|
|
51
69
|
@value.key.should == 'spec/value'
|
|
@@ -86,6 +104,19 @@ describe Redis::Value do
|
|
|
86
104
|
@value.nil?.should == true
|
|
87
105
|
end
|
|
88
106
|
|
|
107
|
+
it 'should set time to live in seconds when expiration option assigned' do
|
|
108
|
+
@value = Redis::Value.new('spec/value', :expiration => 10)
|
|
109
|
+
@value.value = 'monkey'
|
|
110
|
+
@value.ttl.should > 0
|
|
111
|
+
@value.ttl.should <= 10
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should set expiration when expireat option assigned' do
|
|
115
|
+
@value = Redis::Value.new('spec/value', :expireat => Time.now + 10.seconds)
|
|
116
|
+
@value.value = 'monkey'
|
|
117
|
+
@value.ttl.should > 0
|
|
118
|
+
end
|
|
119
|
+
|
|
89
120
|
after do
|
|
90
121
|
@value.delete
|
|
91
122
|
end
|
|
@@ -298,6 +329,20 @@ describe Redis::List do
|
|
|
298
329
|
@list.redis.del('spec/list2')
|
|
299
330
|
end
|
|
300
331
|
|
|
332
|
+
it 'should set time to live in seconds when expiration option assigned' do
|
|
333
|
+
@list = Redis::List.new('spec/list', :expiration => 10)
|
|
334
|
+
@list << 'val'
|
|
335
|
+
@list.ttl.should > 0
|
|
336
|
+
@list.ttl.should <= 10
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it 'should set expiration when expireat option assigned' do
|
|
340
|
+
@list = Redis::List.new('spec/list', :expireat => Time.now + 10.seconds)
|
|
341
|
+
@list << 'val'
|
|
342
|
+
@list.ttl.should > 0
|
|
343
|
+
@list.ttl.should <= 10
|
|
344
|
+
end
|
|
345
|
+
|
|
301
346
|
after do
|
|
302
347
|
@list.clear
|
|
303
348
|
end
|
|
@@ -341,6 +386,33 @@ describe Redis::Counter do
|
|
|
341
386
|
@counter.should == 111
|
|
342
387
|
end
|
|
343
388
|
|
|
389
|
+
it "should support increment/decrement by float" do
|
|
390
|
+
@counter = Redis::Counter.new('spec/floater')
|
|
391
|
+
@counter.set 10.5
|
|
392
|
+
@counter.incrbyfloat 1
|
|
393
|
+
@counter.incrbyfloat 0.01
|
|
394
|
+
@counter.to_f.should == 11.51
|
|
395
|
+
@counter.set '5.0e3'
|
|
396
|
+
@counter.decrbyfloat -14.31
|
|
397
|
+
@counter.incrbyfloat 2.0e2
|
|
398
|
+
@counter.to_f.should == 5214.31
|
|
399
|
+
@counter.clear
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it 'should set time to live in seconds when expiration option assigned' do
|
|
403
|
+
@counter = Redis::Counter.new('spec/counter', :expiration => 10)
|
|
404
|
+
@counter.increment
|
|
405
|
+
@counter.ttl.should > 0
|
|
406
|
+
@counter.ttl.should <= 10
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
it 'should set expiration when expireat option assigned' do
|
|
410
|
+
@counter = Redis::Counter.new('spec/counter', :expireat => Time.now + 10.seconds)
|
|
411
|
+
@counter.increment
|
|
412
|
+
@counter.ttl.should > 0
|
|
413
|
+
@counter.ttl.should <= 10
|
|
414
|
+
end
|
|
415
|
+
|
|
344
416
|
after do
|
|
345
417
|
@counter.delete
|
|
346
418
|
end
|
|
@@ -473,8 +545,8 @@ describe Redis::HashKey do
|
|
|
473
545
|
it "should handle complex marshaled values" do
|
|
474
546
|
@hash.options[:marshal] = true
|
|
475
547
|
@hash['abc'].should == nil
|
|
476
|
-
@hash['abc'] = {:json => '
|
|
477
|
-
@hash['abc'].should == {:json => '
|
|
548
|
+
@hash['abc'] = {:json => 'hash marshal'}
|
|
549
|
+
@hash['abc'].should == {:json => 'hash marshal'}
|
|
478
550
|
|
|
479
551
|
# no marshaling
|
|
480
552
|
@hash.options[:marshal] = false
|
|
@@ -508,6 +580,18 @@ describe Redis::HashKey do
|
|
|
508
580
|
@hash.options[:marshal] = false
|
|
509
581
|
end
|
|
510
582
|
|
|
583
|
+
it "should marshal nil correctly" do
|
|
584
|
+
@hash.options[:marshal] = true
|
|
585
|
+
|
|
586
|
+
@hash['test'].should.be.nil
|
|
587
|
+
@hash['test'] = nil
|
|
588
|
+
@hash['test'].should.be.nil
|
|
589
|
+
@hash.delete('test').should == 1
|
|
590
|
+
@hash['test'].should.be.nil
|
|
591
|
+
|
|
592
|
+
@hash.options[:marshal] = false
|
|
593
|
+
end
|
|
594
|
+
|
|
511
595
|
it "should get and set values" do
|
|
512
596
|
@hash['foo'] = 'bar'
|
|
513
597
|
@hash['foo'].should == 'bar'
|
|
@@ -544,6 +628,29 @@ describe Redis::HashKey do
|
|
|
544
628
|
end
|
|
545
629
|
end
|
|
546
630
|
|
|
631
|
+
it "should handle increment/decrement" do
|
|
632
|
+
@hash['integer'] = 1
|
|
633
|
+
@hash.incrby('integer')
|
|
634
|
+
@hash.incrby('integer', 2)
|
|
635
|
+
@hash.get('integer').to_i.should == 4
|
|
636
|
+
|
|
637
|
+
@hash['integer'] = 9
|
|
638
|
+
@hash.decrby('integer')
|
|
639
|
+
@hash.decrby('integer', 6)
|
|
640
|
+
@hash.get('integer').to_i.should == 2
|
|
641
|
+
|
|
642
|
+
@hash['float'] = 12.34
|
|
643
|
+
@hash.decrbyfloat('float')
|
|
644
|
+
@hash.decrbyfloat('float', 6.3)
|
|
645
|
+
@hash.get('float').to_f.should == 5.04
|
|
646
|
+
|
|
647
|
+
@hash['float'] = '5.0e3'
|
|
648
|
+
@hash.incrbyfloat('float')
|
|
649
|
+
@hash.incrbyfloat('float', '1.23e3')
|
|
650
|
+
@hash.incrbyfloat('float', 45.3)
|
|
651
|
+
@hash.get('float').to_f.should == 6276.3
|
|
652
|
+
end
|
|
653
|
+
|
|
547
654
|
it "should respond to each_value" do
|
|
548
655
|
@hash['foo'] = 'bar'
|
|
549
656
|
@hash.each_value do |val|
|
|
@@ -603,6 +710,31 @@ describe Redis::HashKey do
|
|
|
603
710
|
end
|
|
604
711
|
end
|
|
605
712
|
|
|
713
|
+
it "should fetch default values" do
|
|
714
|
+
@hash['abc'] = "123"
|
|
715
|
+
|
|
716
|
+
value = @hash.fetch('missing_key','default_value')
|
|
717
|
+
block = @hash.fetch("missing_key") {|key| "oops: #{key}" }
|
|
718
|
+
no_error = @hash.fetch("abc") rescue "error"
|
|
719
|
+
|
|
720
|
+
no_error.should == "123"
|
|
721
|
+
value.should == "default_value"
|
|
722
|
+
block.should == "oops: missing_key"
|
|
723
|
+
end
|
|
724
|
+
|
|
725
|
+
it 'should set time to live in seconds when expiration option assigned' do
|
|
726
|
+
@hash = Redis::HashKey.new('spec/hash_key', :expiration => 10)
|
|
727
|
+
@hash['foo'] = 'bar'
|
|
728
|
+
@hash.ttl.should > 0
|
|
729
|
+
@hash.ttl.should <= 10
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
it 'should set expiration when expireat option assigned' do
|
|
733
|
+
@hash = Redis::HashKey.new('spec/hash_key', :expireat => Time.now + 10.seconds)
|
|
734
|
+
@hash['foo'] = 'bar'
|
|
735
|
+
@hash.ttl.should > 0
|
|
736
|
+
end
|
|
737
|
+
|
|
606
738
|
after do
|
|
607
739
|
@hash.clear
|
|
608
740
|
end
|
|
@@ -665,6 +797,17 @@ describe Redis::Set do
|
|
|
665
797
|
@set.sort.should == ['a','b','c']
|
|
666
798
|
@set.delete_if{|m| m == 'c'}
|
|
667
799
|
@set.sort.should == ['a','b']
|
|
800
|
+
|
|
801
|
+
@set << nil
|
|
802
|
+
@set.include?("").should.be.true
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
it "should handle empty array adds" do
|
|
806
|
+
should.not.raise(Redis::CommandError) { @set.add([]) }
|
|
807
|
+
@set.should.be.empty
|
|
808
|
+
|
|
809
|
+
should.not.raise(Redis::CommandError) { @set << [] }
|
|
810
|
+
@set.should.be.empty
|
|
668
811
|
end
|
|
669
812
|
|
|
670
813
|
it "should handle set intersections, unions, and diffs" do
|
|
@@ -764,7 +907,20 @@ describe Redis::Set do
|
|
|
764
907
|
@set_1.redis.del val1.key
|
|
765
908
|
@set_1.redis.del val2.key
|
|
766
909
|
@set_1.redis.del SORT_STORE[:store]
|
|
910
|
+
end
|
|
767
911
|
|
|
912
|
+
it 'should set time to live in seconds when expiration option assigned' do
|
|
913
|
+
@set = Redis::Set.new('spec/set', :expiration => 10)
|
|
914
|
+
@set << 'val'
|
|
915
|
+
@set.ttl.should > 0
|
|
916
|
+
@set.ttl.should <= 10
|
|
917
|
+
end
|
|
918
|
+
|
|
919
|
+
it 'should set expiration when expireat option assigned' do
|
|
920
|
+
@set = Redis::Set.new('spec/set', :expireat => Time.now + 10.seconds)
|
|
921
|
+
@set << 'val'
|
|
922
|
+
@set.ttl.should > 0
|
|
923
|
+
@set.ttl.should <= 10
|
|
768
924
|
end
|
|
769
925
|
|
|
770
926
|
after do
|
|
@@ -810,6 +966,7 @@ describe Redis::SortedSet do
|
|
|
810
966
|
@set.range(0, 2).should == a[0..2]
|
|
811
967
|
@set[0, 0].should == []
|
|
812
968
|
@set.range(0,1,:withscores => true).should == [['a',3],['c',4]]
|
|
969
|
+
@set.revrange(0,1,:withscores => true).should == [['b',5.6],['c',4]]
|
|
813
970
|
@set.range(0,-1).should == a[0..-1]
|
|
814
971
|
@set.revrange(0,-1).should == a[0..-1].reverse
|
|
815
972
|
@set[0..1].should == a[0..1]
|
|
@@ -823,6 +980,8 @@ describe Redis::SortedSet do
|
|
|
823
980
|
@set.members(:withscores => true).should == [['a',3],['c',4],['b',5.6]]
|
|
824
981
|
@set.members(:with_scores => true).should == [['a',3],['c',4],['b',5.6]]
|
|
825
982
|
@set.members(:withscores => true).reverse.should == [['b',5.6],['c',4],['a',3]]
|
|
983
|
+
@set.members(:withscores => true).should == @set.range(0,-1,:withscores => true)
|
|
984
|
+
@set.members(:withscores => true).reverse.should == @set.revrange(0,-1,:withscores => true)
|
|
826
985
|
|
|
827
986
|
@set['b'] = 5
|
|
828
987
|
@set['b'] = 6
|
|
@@ -882,13 +1041,33 @@ describe Redis::SortedSet do
|
|
|
882
1041
|
@set.size.should == 3
|
|
883
1042
|
end
|
|
884
1043
|
|
|
1044
|
+
it "should handle inserting multiple values at once" do
|
|
1045
|
+
@set.merge({ 'a' => 1, 'b' => 2 })
|
|
1046
|
+
@set.merge([['a', 4], ['c', 5]])
|
|
1047
|
+
@set.merge({d: 0, e: 9 })
|
|
1048
|
+
|
|
1049
|
+
@set.members.should == ["d", "b", "a", "c", "e"]
|
|
1050
|
+
|
|
1051
|
+
@set[:f] = 3
|
|
1052
|
+
@set.members.should == ["d", "b", "f", "a", "c", "e"]
|
|
1053
|
+
end
|
|
1054
|
+
|
|
885
1055
|
it "should support marshaling key names" do
|
|
1056
|
+
@set_4.members.should == []
|
|
1057
|
+
|
|
886
1058
|
@set_4[Object] = 1.20
|
|
887
1059
|
@set_4[Module] = 2.30
|
|
1060
|
+
@set_4[nil] = 3.40
|
|
1061
|
+
|
|
888
1062
|
@set_4.incr(Object, 0.5)
|
|
889
1063
|
@set_4.decr(Module, 0.5)
|
|
1064
|
+
@set_4.incr(nil, 0.5)
|
|
1065
|
+
|
|
890
1066
|
@set_4[Object].round(1).should == 1.7
|
|
891
1067
|
@set_4[Module].round(1).should == 1.8
|
|
1068
|
+
@set_4[nil].round(1).should == 3.9
|
|
1069
|
+
|
|
1070
|
+
@set_4.members.should == [Object, Module, nil]
|
|
892
1071
|
end
|
|
893
1072
|
|
|
894
1073
|
it "should support renaming sorted sets" do
|
|
@@ -909,6 +1088,20 @@ describe Redis::SortedSet do
|
|
|
909
1088
|
@set.redis.del('spec/zset2')
|
|
910
1089
|
end
|
|
911
1090
|
|
|
1091
|
+
it 'should set time to live in seconds when expiration option assigned' do
|
|
1092
|
+
@set = Redis::SortedSet.new('spec/zset', :expiration => 10)
|
|
1093
|
+
@set['val'] = 1
|
|
1094
|
+
@set.ttl.should > 0
|
|
1095
|
+
@set.ttl.should <= 10
|
|
1096
|
+
end
|
|
1097
|
+
|
|
1098
|
+
it 'should set expiration when expireat option assigned' do
|
|
1099
|
+
@set = Redis::SortedSet.new('spec/zset', :expireat => Time.now + 10.seconds)
|
|
1100
|
+
@set['val'] = 1
|
|
1101
|
+
@set.ttl.should > 0
|
|
1102
|
+
@set.ttl.should <= 10
|
|
1103
|
+
end
|
|
1104
|
+
|
|
912
1105
|
after do
|
|
913
1106
|
@set.clear
|
|
914
1107
|
@set_1.clear
|