redis-objects 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +36 -12
- data/Gemfile +6 -0
- data/Gemfile.lock +43 -0
- data/Rakefile +6 -6
- data/VERSION +1 -1
- data/lib/redis/hash_key.rb +7 -0
- data/lib/redis/helpers/core_commands.rb +1 -1
- data/lib/redis/list.rb +10 -0
- data/lib/redis/objects/counters.rb +7 -5
- data/lib/redis/set.rb +7 -1
- data/lib/redis/sorted_set.rb +11 -29
- data/redis-objects.gemspec +27 -10
- data/spec/redis_objects_active_record_spec.rb +30 -0
- data/spec/redis_objects_instance_spec.rb +37 -17
- data/spec/redis_objects_model_spec.rb +18 -19
- data/spec/spec_helper.rb +3 -2
- metadata +112 -12
data/CHANGELOG.rdoc
CHANGED
@@ -1,12 +1,36 @@
|
|
1
1
|
= Changelog for Redis::Objects
|
2
2
|
|
3
|
-
== 0.
|
3
|
+
== 0.6.0 (24 October 2012)
|
4
|
+
|
5
|
+
* Add +@set.merge()+ method to add multiple members at once [hfwang]
|
6
|
+
|
7
|
+
* Add +insert+ method to Redis::List instances [giglemad]
|
8
|
+
|
9
|
+
* Updated APIs for recent redis-server sort API compat [nateware]
|
10
|
+
|
11
|
+
* Add HashKey#bulk_values for fetching values in the same order than the given keys [aspgems]
|
12
|
+
|
13
|
+
* Lists now handle the insert command
|
14
|
+
|
15
|
+
* Changed +@sset.score+ method on SortedSet to return nil for invalid members [hkarthik]
|
16
|
+
|
17
|
+
* Test using redis-objects counters and fix when AR passes a string
|
18
|
+
|
19
|
+
* Add LSET to lists [neonlex]
|
20
|
+
|
21
|
+
* Fix interstore/unionstore for redis 2.6 [david]
|
22
|
+
|
23
|
+
* Redis-rb 3.0.0 support [seomoz]
|
24
|
+
|
25
|
+
* group_set_with_scores is no longer needed.
|
26
|
+
|
27
|
+
== 0.5.2 (13 June 2012)
|
4
28
|
|
5
29
|
* Added Redis::SortedSet#member? method [Karl Varga]
|
6
30
|
|
7
31
|
* Added +ttl+ method to CoreCommands [Karl Varga]
|
8
32
|
|
9
|
-
== 0.5.1
|
33
|
+
== 0.5.1 (23 May 2011)
|
10
34
|
|
11
35
|
* Fixed super class delegation conflicts with Redis Counters vs ActiveRecord [Tim Aßmann]
|
12
36
|
|
@@ -16,7 +40,7 @@
|
|
16
40
|
|
17
41
|
* Updated URLs to reflect new redis.io website [Jérémy Lecour]
|
18
42
|
|
19
|
-
== 0.5.0
|
43
|
+
== 0.5.0 (8 November 2010)
|
20
44
|
|
21
45
|
* Incompatible change: Had to rename Redis::Hash to Redis::HashKey due to internal conflicts with Redis lib and Ruby [Nate Wiger]
|
22
46
|
|
@@ -30,7 +54,7 @@
|
|
30
54
|
|
31
55
|
* Updated Redis DEL semantics per API change [Gabe da Silveira]
|
32
56
|
|
33
|
-
== 0.4.1
|
57
|
+
== 0.4.1 (23 August 2010)
|
34
58
|
|
35
59
|
* Fixes for Ruby 1.8 failures due to missing flatten() [Gabe da Silveira]
|
36
60
|
|
@@ -40,7 +64,7 @@
|
|
40
64
|
|
41
65
|
* Fixed a typo in delete_if and added missing test coverage [Julio Capote, Nate Wiger]
|
42
66
|
|
43
|
-
== 0.4.0
|
67
|
+
== 0.4.0 (11 August 2010)
|
44
68
|
|
45
69
|
* Full support for redis hashes via new Redis::Hash class [Julio Capote, Nate Wiger]
|
46
70
|
|
@@ -54,7 +78,7 @@
|
|
54
78
|
|
55
79
|
* Renamed :withscores option to :with_scores for consistency with redis-rb 2.0, but kept backwards compat [Tom Stuart, Nate Wiger]
|
56
80
|
|
57
|
-
== 0.3.2
|
81
|
+
== 0.3.2 (21 July 2010)
|
58
82
|
|
59
83
|
* New "maxlength" option to Redis::List can create length-limited lists (eg, like a ring buffer) from dbalatero [David Balatero]
|
60
84
|
|
@@ -62,21 +86,21 @@
|
|
62
86
|
|
63
87
|
* Switched from rspec to bacon for tests
|
64
88
|
|
65
|
-
== 0.3.1
|
89
|
+
== 0.3.1 (1 June 2010)
|
66
90
|
|
67
91
|
* Integrated fixes for sorted_set deletions from capotej [Julio Capote]
|
68
92
|
|
69
|
-
== 0.3.0
|
93
|
+
== 0.3.0 (14 April 2010)
|
70
94
|
|
71
95
|
* Due to Ruby 1.9 bugs and performance considerations, marshaling of data types is now OFF by default. You must say :marshal => true for any objects that you want serialization enabled on. [Nate Wiger]
|
72
96
|
|
73
97
|
* Sorted Set class changed slightly due to feedback. You can now get an individual element back via @set['item'] since it acts like a Hash.
|
74
98
|
|
75
|
-
== 0.2.4
|
99
|
+
== 0.2.4 (9 April 2010)
|
76
100
|
|
77
101
|
* Added sorted set support via Redis::SortedSet [Nate Wiger]
|
78
102
|
|
79
|
-
== 0.2.3
|
103
|
+
== 0.2.3 (18 February 2010)
|
80
104
|
|
81
105
|
* Added lock expiration to Redis::Lock [Ben VandenBos]
|
82
106
|
|
@@ -84,7 +108,7 @@
|
|
84
108
|
|
85
109
|
* Added lock tests and test helpers [Ben VandenBos]
|
86
110
|
|
87
|
-
== 0.2.2
|
111
|
+
== 0.2.2 (14 December 2009)
|
88
112
|
|
89
113
|
* Added @set.diff(@set2) with "^" and "-" synonyms (oversight). [Nate Wiger]
|
90
114
|
|
@@ -94,7 +118,7 @@
|
|
94
118
|
|
95
119
|
* More spec coverage. [Nate Wiger]
|
96
120
|
|
97
|
-
== 0.2.1
|
121
|
+
== 0.2.1 (27 November 2009)
|
98
122
|
|
99
123
|
* First worthwhile public release, with good spec coverage and functionality. [Nate Wiger]
|
100
124
|
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (3.2.8)
|
5
|
+
activesupport (= 3.2.8)
|
6
|
+
builder (~> 3.0.0)
|
7
|
+
activerecord (3.2.8)
|
8
|
+
activemodel (= 3.2.8)
|
9
|
+
activesupport (= 3.2.8)
|
10
|
+
arel (~> 3.0.2)
|
11
|
+
tzinfo (~> 0.3.29)
|
12
|
+
activesupport (3.2.8)
|
13
|
+
i18n (~> 0.6)
|
14
|
+
multi_json (~> 1.0)
|
15
|
+
arel (3.0.2)
|
16
|
+
bacon (1.1.0)
|
17
|
+
builder (3.0.4)
|
18
|
+
git (1.2.5)
|
19
|
+
i18n (0.6.1)
|
20
|
+
jeweler (1.8.4)
|
21
|
+
bundler (~> 1.0)
|
22
|
+
git (>= 1.2.5)
|
23
|
+
rake
|
24
|
+
rdoc
|
25
|
+
json (1.7.5)
|
26
|
+
multi_json (1.3.6)
|
27
|
+
rake (0.9.2.2)
|
28
|
+
rdoc (3.12)
|
29
|
+
json (~> 1.4)
|
30
|
+
redis (3.0.2)
|
31
|
+
redis-namespace (1.2.1)
|
32
|
+
redis (~> 3.0.0)
|
33
|
+
tzinfo (0.3.33)
|
34
|
+
|
35
|
+
PLATFORMS
|
36
|
+
ruby
|
37
|
+
|
38
|
+
DEPENDENCIES
|
39
|
+
activerecord
|
40
|
+
bacon
|
41
|
+
jeweler
|
42
|
+
redis (>= 3.0.2)
|
43
|
+
redis-namespace
|
data/Rakefile
CHANGED
@@ -11,9 +11,9 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/nateware/redis-objects"
|
12
12
|
gem.authors = ["Nate Wiger"]
|
13
13
|
gem.add_development_dependency "bacon", ">= 0"
|
14
|
-
gem.add_development_dependency "redis-namespace", ">= 0"
|
15
|
-
gem.requirements << 'redis,
|
16
|
-
gem.add_dependency('redis', '>=
|
14
|
+
gem.add_development_dependency "redis-namespace", ">= 1.2.0"
|
15
|
+
gem.requirements << 'redis, v3.0.2 or greater'
|
16
|
+
gem.add_dependency('redis', '>= 3.0.2') # ALSO: update spec/spec_helper.rb
|
17
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
18
|
end
|
19
19
|
Jeweler::GemcutterTasks.new
|
@@ -21,7 +21,7 @@ rescue LoadError
|
|
21
21
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
22
|
end
|
23
23
|
|
24
|
-
# require '
|
24
|
+
# require 'rdoc/task'
|
25
25
|
# Rake::TestTask.new(:spec) do |spec|
|
26
26
|
# spec.libs << 'lib' << 'spec'
|
27
27
|
# spec.pattern = 'spec/**/*_spec.rb'
|
@@ -30,7 +30,7 @@ end
|
|
30
30
|
|
31
31
|
desc "run all the specs"
|
32
32
|
task :test do
|
33
|
-
sh "bacon spec/*_spec.rb"
|
33
|
+
sh "bundle exec bacon spec/*_spec.rb"
|
34
34
|
end
|
35
35
|
|
36
36
|
|
@@ -51,7 +51,7 @@ task :spec => :check_dependencies
|
|
51
51
|
|
52
52
|
task :default => :spec
|
53
53
|
|
54
|
-
require '
|
54
|
+
require 'rdoc/task'
|
55
55
|
Rake::RDocTask.new do |rdoc|
|
56
56
|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
57
57
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/redis/hash_key.rb
CHANGED
@@ -135,6 +135,13 @@ class Redis
|
|
135
135
|
hsh
|
136
136
|
end
|
137
137
|
|
138
|
+
# Get values in bulk, takes an array of keys as arguments.
|
139
|
+
# Values are returned in a collection in the same order than their keys in *keys Redis: HMGET
|
140
|
+
def bulk_values(*keys)
|
141
|
+
res = redis.hmget(key, *keys.flatten)
|
142
|
+
keys.inject([]){|collection, k| collection << from_redis(res.shift)}
|
143
|
+
end
|
144
|
+
|
138
145
|
# Increment value by integer at field. Redis: HINCRBY
|
139
146
|
def incrby(field, val = 1)
|
140
147
|
ret = redis.hincrby(key, field, val)
|
data/lib/redis/list.rb
CHANGED
@@ -20,6 +20,11 @@ class Redis
|
|
20
20
|
push(value)
|
21
21
|
self # for << 'a' << 'b'
|
22
22
|
end
|
23
|
+
|
24
|
+
# Add a member before or after pivot in the list. Redis: LINSERT
|
25
|
+
def insert(where,pivot,value)
|
26
|
+
redis.linsert(key,where,to_redis(pivot),to_redis(value))
|
27
|
+
end
|
23
28
|
|
24
29
|
# Add a member to the end of the list. Redis: RPUSH
|
25
30
|
def push(value)
|
@@ -81,6 +86,11 @@ class Redis
|
|
81
86
|
end
|
82
87
|
alias_method :slice, :[]
|
83
88
|
|
89
|
+
# Same functionality as Ruby arrays.
|
90
|
+
def []=(index, value)
|
91
|
+
redis.lset(key, index, value)
|
92
|
+
end
|
93
|
+
|
84
94
|
# Delete the element(s) from the list that match name. If count is specified,
|
85
95
|
# only the first-N (if positive) or last-N (if negative) will be removed.
|
86
96
|
# Use .del to completely delete the entire key.
|
@@ -55,6 +55,7 @@ class Redis
|
|
55
55
|
# Increment a counter with the specified name and id. Accepts a block
|
56
56
|
# like the instance method. See Redis::Objects::Counter for details.
|
57
57
|
def increment_counter(name, id=nil, by=1, &block)
|
58
|
+
name = name.to_sym
|
58
59
|
return super(name, id) unless counter_defined?(name)
|
59
60
|
verify_counter_defined!(name, id)
|
60
61
|
initialize_counter!(name, id)
|
@@ -65,6 +66,7 @@ class Redis
|
|
65
66
|
# Decrement a counter with the specified name and id. Accepts a block
|
66
67
|
# like the instance method. See Redis::Objects::Counter for details.
|
67
68
|
def decrement_counter(name, id=nil, by=1, &block)
|
69
|
+
name = name.to_sym
|
68
70
|
return super(name, id) unless counter_defined?(name)
|
69
71
|
verify_counter_defined!(name, id)
|
70
72
|
initialize_counter!(name, id)
|
@@ -86,20 +88,20 @@ class Redis
|
|
86
88
|
to = @redis_objects[name][:start] if to.nil?
|
87
89
|
redis.getset(redis_field_key(name, id), to.to_i).to_i
|
88
90
|
end
|
89
|
-
|
91
|
+
|
90
92
|
private
|
91
|
-
|
93
|
+
|
92
94
|
def verify_counter_defined!(name, id) #:nodoc:
|
93
95
|
raise NoMethodError, "Undefined counter :#{name} for class #{self.name}" unless counter_defined?(name)
|
94
96
|
if id.nil? and !@redis_objects[name][:global]
|
95
97
|
raise Redis::Objects::MissingID, "Missing ID for non-global counter #{self.name}##{name}"
|
96
98
|
end
|
97
99
|
end
|
98
|
-
|
100
|
+
|
99
101
|
def counter_defined?(name) #:nodoc:
|
100
102
|
@redis_objects && @redis_objects.has_key?(name)
|
101
103
|
end
|
102
|
-
|
104
|
+
|
103
105
|
def initialize_counter!(name, id) #:nodoc:
|
104
106
|
key = redis_field_key(name, id)
|
105
107
|
unless @initialized_counters[key]
|
@@ -107,7 +109,7 @@ class Redis
|
|
107
109
|
end
|
108
110
|
@initialized_counters[key] = true
|
109
111
|
end
|
110
|
-
|
112
|
+
|
111
113
|
# Implements increment/decrement blocks on a class level
|
112
114
|
def rewindable_block(rewind, name, id, value, &block) #:nodoc:
|
113
115
|
# Unfortunately this is almost exactly duplicated from Redis::Counter
|
data/lib/redis/set.rb
CHANGED
@@ -26,11 +26,17 @@ class Redis
|
|
26
26
|
redis.sadd(key, to_redis(value))
|
27
27
|
end
|
28
28
|
|
29
|
-
# Remove and return a random member. Redis:SPOP
|
29
|
+
# Remove and return a random member. Redis: SPOP
|
30
30
|
def pop
|
31
31
|
from_redis redis.spop(key)
|
32
32
|
end
|
33
33
|
|
34
|
+
# Adds the specified values to the set. Only works on redis > 2.4
|
35
|
+
# Redis: SADD
|
36
|
+
def merge(*values)
|
37
|
+
redis.sadd(key, values.flatten.map{|v| to_redis(v)})
|
38
|
+
end
|
39
|
+
|
34
40
|
# Return all members in the set. Redis: SMEMBERS
|
35
41
|
def members
|
36
42
|
v = from_redis redis.smembers(key)
|
data/lib/redis/sorted_set.rb
CHANGED
@@ -41,7 +41,7 @@ class Redis
|
|
41
41
|
when -1 then nil # Ruby does this (a bit weird)
|
42
42
|
end
|
43
43
|
else
|
44
|
-
score(index)
|
44
|
+
result = score(index) || 0 # handles a nil score
|
45
45
|
end
|
46
46
|
end
|
47
47
|
alias_method :slice, :[]
|
@@ -50,7 +50,9 @@ class Redis
|
|
50
50
|
# specified element does not exist in the sorted set, or the key does not exist
|
51
51
|
# at all, nil is returned. Redis: ZSCORE.
|
52
52
|
def score(member)
|
53
|
-
redis.zscore(key, to_redis(member))
|
53
|
+
result = redis.zscore(key, to_redis(member))
|
54
|
+
|
55
|
+
result.to_f unless result.nil?
|
54
56
|
end
|
55
57
|
|
56
58
|
# Return the rank of the member in the sorted set, with scores ordered from
|
@@ -84,8 +86,7 @@ class Redis
|
|
84
86
|
# the familiar list[start,end] Ruby syntax. Redis: ZRANGE
|
85
87
|
def range(start_index, end_index, options={})
|
86
88
|
if options[:withscores] || options[:with_scores]
|
87
|
-
|
88
|
-
group_set_with_scores(val)
|
89
|
+
from_redis redis.zrange(key, start_index, end_index, :with_scores => true)
|
89
90
|
else
|
90
91
|
from_redis redis.zrange(key, start_index, end_index)
|
91
92
|
end
|
@@ -94,8 +95,7 @@ class Redis
|
|
94
95
|
# Return a range of values from +start_index+ to +end_index+ in reverse order. Redis: ZREVRANGE
|
95
96
|
def revrange(start_index, end_index, options={})
|
96
97
|
if options[:withscores] || options[:with_scores]
|
97
|
-
|
98
|
-
group_set_with_scores(val)
|
98
|
+
from_redis redis.zrevrange(key, start_index, end_index, :with_scores => true)
|
99
99
|
else
|
100
100
|
from_redis redis.zrevrange(key, start_index, end_index)
|
101
101
|
end
|
@@ -112,12 +112,7 @@ class Redis
|
|
112
112
|
options[:offset] || options[:limit] || options[:count]
|
113
113
|
args[:with_scores] = true if options[:withscores] || options[:with_scores]
|
114
114
|
|
115
|
-
|
116
|
-
val = from_redis redis.zrangebyscore(key, min, max, args)
|
117
|
-
group_set_with_scores(val)
|
118
|
-
else
|
119
|
-
from_redis redis.zrangebyscore(key, min, max, args)
|
120
|
-
end
|
115
|
+
from_redis redis.zrangebyscore(key, min, max, args)
|
121
116
|
end
|
122
117
|
|
123
118
|
# Forwards compat (not yet implemented in Redis)
|
@@ -127,12 +122,7 @@ class Redis
|
|
127
122
|
options[:offset] || options[:limit] || options[:count]
|
128
123
|
args[:with_scores] = true if options[:withscores] || options[:with_scores]
|
129
124
|
|
130
|
-
|
131
|
-
val = from_redis redis.zrevrangebyscore(key, min, max, args)
|
132
|
-
group_set_with_scores(val)
|
133
|
-
else
|
134
|
-
from_redis redis.zrevrangebyscore(key, min, max, args)
|
135
|
-
end
|
125
|
+
from_redis redis.zrevrangebyscore(key, min, max, args)
|
136
126
|
end
|
137
127
|
|
138
128
|
# Remove all elements in the sorted set at key with rank between start and end. Start and end are
|
@@ -203,7 +193,7 @@ class Redis
|
|
203
193
|
# Calculate the intersection and store it in Redis as +name+. Returns the number
|
204
194
|
# of elements in the stored intersection. Redis: SUNIONSTORE
|
205
195
|
def interstore(name, *sets)
|
206
|
-
redis.zinterstore(name,
|
196
|
+
redis.zinterstore(name, keys_from_objects([self] + sets))
|
207
197
|
end
|
208
198
|
|
209
199
|
# Return the union with another set. Can pass it either another set
|
@@ -226,7 +216,7 @@ class Redis
|
|
226
216
|
# Calculate the union and store it in Redis as +name+. Returns the number
|
227
217
|
# of elements in the stored union. Redis: SUNIONSTORE
|
228
218
|
def unionstore(name, *sets)
|
229
|
-
redis.zunionstore(name,
|
219
|
+
redis.zunionstore(name, keys_from_objects([self] + sets))
|
230
220
|
end
|
231
221
|
|
232
222
|
# Return the difference vs another set. Can pass it either another set
|
@@ -288,7 +278,7 @@ class Redis
|
|
288
278
|
redis.zcard(key)
|
289
279
|
end
|
290
280
|
alias_method :size, :length
|
291
|
-
|
281
|
+
|
292
282
|
# The number of members within a range of scores. Redis: ZCOUNT
|
293
283
|
def range_size(min, max)
|
294
284
|
redis.zcount(key, min, max)
|
@@ -305,13 +295,5 @@ class Redis
|
|
305
295
|
raise ArgumentError, "Must pass in one or more set names" if sets.empty?
|
306
296
|
sets.collect{|set| set.is_a?(Redis::SortedSet) ? set.key : set}
|
307
297
|
end
|
308
|
-
|
309
|
-
def group_set_with_scores(set_with_scores)
|
310
|
-
ret = []
|
311
|
-
while k = set_with_scores.shift and v = set_with_scores.shift
|
312
|
-
ret << [k, v.to_f]
|
313
|
-
end
|
314
|
-
ret
|
315
|
-
end
|
316
298
|
end
|
317
299
|
end
|
data/redis-objects.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "redis-objects"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.6.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nate Wiger"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-10-24"
|
13
13
|
s.description = "Map Redis types directly to Ruby objects. Works with any class or ORM."
|
14
14
|
s.email = "nate@wiger.org"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -18,6 +18,8 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.files = [
|
19
19
|
"ATOMICITY.rdoc",
|
20
20
|
"CHANGELOG.rdoc",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
21
23
|
"README.rdoc",
|
22
24
|
"Rakefile",
|
23
25
|
"VERSION",
|
@@ -48,26 +50,41 @@ Gem::Specification.new do |s|
|
|
48
50
|
]
|
49
51
|
s.homepage = "http://github.com/nateware/redis-objects"
|
50
52
|
s.require_paths = ["lib"]
|
51
|
-
s.requirements = ["redis,
|
52
|
-
s.rubygems_version = "1.8.
|
53
|
+
s.requirements = ["redis, v3.0.2 or greater"]
|
54
|
+
s.rubygems_version = "1.8.24"
|
53
55
|
s.summary = "Map Redis types directly to Ruby objects"
|
54
56
|
|
55
57
|
if s.respond_to? :specification_version then
|
56
58
|
s.specification_version = 3
|
57
59
|
|
58
60
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
61
|
+
s.add_runtime_dependency(%q<redis>, [">= 3.0.2"])
|
62
|
+
s.add_runtime_dependency(%q<redis-namespace>, [">= 0"])
|
63
|
+
s.add_runtime_dependency(%q<bacon>, [">= 0"])
|
64
|
+
s.add_runtime_dependency(%q<jeweler>, [">= 0"])
|
65
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
59
66
|
s.add_development_dependency(%q<bacon>, [">= 0"])
|
60
|
-
s.add_development_dependency(%q<redis-namespace>, [">= 0"])
|
61
|
-
s.add_runtime_dependency(%q<redis>, [">=
|
67
|
+
s.add_development_dependency(%q<redis-namespace>, [">= 1.2.0"])
|
68
|
+
s.add_runtime_dependency(%q<redis>, [">= 3.0.2"])
|
62
69
|
else
|
63
|
-
s.add_dependency(%q<
|
70
|
+
s.add_dependency(%q<redis>, [">= 3.0.2"])
|
64
71
|
s.add_dependency(%q<redis-namespace>, [">= 0"])
|
65
|
-
s.add_dependency(%q<
|
72
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
73
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
74
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
75
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
76
|
+
s.add_dependency(%q<redis-namespace>, [">= 1.2.0"])
|
77
|
+
s.add_dependency(%q<redis>, [">= 3.0.2"])
|
66
78
|
end
|
67
79
|
else
|
68
|
-
s.add_dependency(%q<
|
80
|
+
s.add_dependency(%q<redis>, [">= 3.0.2"])
|
69
81
|
s.add_dependency(%q<redis-namespace>, [">= 0"])
|
70
|
-
s.add_dependency(%q<
|
82
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
83
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
84
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
85
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
86
|
+
s.add_dependency(%q<redis-namespace>, [">= 1.2.0"])
|
87
|
+
s.add_dependency(%q<redis>, [">= 3.0.2"])
|
71
88
|
end
|
72
89
|
end
|
73
90
|
|
@@ -49,16 +49,37 @@ begin
|
|
49
49
|
class Post < ActiveRecord::Base
|
50
50
|
include Redis::Objects
|
51
51
|
counter :total
|
52
|
+
counter :comments_count
|
52
53
|
belongs_to :blog, :counter_cache => true
|
53
54
|
end
|
54
55
|
|
56
|
+
class CreateComments < ActiveRecord::Migration
|
57
|
+
def self.up
|
58
|
+
create_table :comments do |t|
|
59
|
+
t.string :body
|
60
|
+
t.integer :post_id
|
61
|
+
t.timestamps
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.down
|
66
|
+
drop_table :comments
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Comment < ActiveRecord::Base
|
71
|
+
include Redis::Objects
|
72
|
+
belongs_to :post, :counter_cache => true
|
73
|
+
end
|
55
74
|
|
56
75
|
describe Redis::Objects do
|
57
76
|
before do
|
77
|
+
CreateComments.up
|
58
78
|
CreatePosts.up
|
59
79
|
CreateBlogs.up
|
60
80
|
end
|
61
81
|
after do
|
82
|
+
CreateComments.down
|
62
83
|
CreatePosts.down
|
63
84
|
CreateBlogs.down
|
64
85
|
end
|
@@ -88,6 +109,15 @@ begin
|
|
88
109
|
@ar2.destroy
|
89
110
|
end
|
90
111
|
|
112
|
+
it "uses the redis objects counter cache when present" do
|
113
|
+
post = Post.create
|
114
|
+
post.comments_count.should == 0
|
115
|
+
comment = Comment.create :post => post
|
116
|
+
post.reload.comments_count.should == 1
|
117
|
+
comment.destroy
|
118
|
+
post.reload.comments_count.should == 0
|
119
|
+
end
|
120
|
+
|
91
121
|
it "falls back to ActiveRecord if redis counter is not defined" do
|
92
122
|
blog = Blog.create
|
93
123
|
blog.reload.posts_count.should == 0
|
@@ -230,6 +230,15 @@ describe Redis::List do
|
|
230
230
|
list2.should == ["b"]
|
231
231
|
end
|
232
232
|
|
233
|
+
it "should handle insert" do
|
234
|
+
@list << 'b' << 'd'
|
235
|
+
@list.insert(:before,'b','a')
|
236
|
+
@list.insert(:after,'b','c')
|
237
|
+
@list.insert("before",'a','z')
|
238
|
+
@list.insert("after",'d','e')
|
239
|
+
@list.should == ['z','a','b','c','d','e']
|
240
|
+
end
|
241
|
+
|
233
242
|
it "should handle lists of complex data types" do
|
234
243
|
@list.options[:marshal] = true
|
235
244
|
v1 = {:json => 'data'}
|
@@ -596,18 +605,18 @@ describe Redis::Set do
|
|
596
605
|
@set.should.be.empty
|
597
606
|
@set << 'a' << 'a' << 'a'
|
598
607
|
@set.should == ['a']
|
608
|
+
@set.to_s.should == 'a'
|
599
609
|
@set.get.should == ['a']
|
600
610
|
@set << 'b' << 'b'
|
601
|
-
@set.
|
602
|
-
@set.should == ['a','b']
|
603
|
-
@set.members.should == ['
|
604
|
-
@set.
|
605
|
-
@set.get.should == ['a','b']
|
611
|
+
@set.sort.should == ['a','b']
|
612
|
+
@set.members.sort.should == ['a','b']
|
613
|
+
@set.members.sort.reverse.should == ['b','a'] # common question
|
614
|
+
@set.get.sort.should == ['a','b']
|
606
615
|
@set << 'c'
|
607
616
|
@set.sort.should == ['a','b','c']
|
608
617
|
@set.get.sort.should == ['a','b','c']
|
609
618
|
@set.delete('c')
|
610
|
-
@set.should == ['a','b']
|
619
|
+
@set.sort.should == ['a','b']
|
611
620
|
@set.get.sort.should == ['a','b']
|
612
621
|
@set.length.should == 2
|
613
622
|
@set.size.should == 2
|
@@ -623,10 +632,10 @@ describe Redis::Set do
|
|
623
632
|
end
|
624
633
|
i.should == @set.length
|
625
634
|
|
626
|
-
coll = @set.collect{|st| st}
|
635
|
+
coll = @set.sort.collect{|st| st}
|
627
636
|
coll.should == ['a','b']
|
628
|
-
@set.should == ['a','b']
|
629
|
-
@set.get.should == ['a','b']
|
637
|
+
@set.sort.should == ['a','b']
|
638
|
+
@set.get.sort.should == ['a','b']
|
630
639
|
|
631
640
|
@set << 'c'
|
632
641
|
@set.member?('c').should.be.true
|
@@ -694,17 +703,27 @@ describe Redis::Set do
|
|
694
703
|
@set.redis.del('spec/set2')
|
695
704
|
end
|
696
705
|
|
706
|
+
it "should handle variadic sadd operations" do
|
707
|
+
@set.should.be.empty
|
708
|
+
@set << 'a'
|
709
|
+
@set.merge('b', 'c')
|
710
|
+
@set.members.sort.should == ['a', 'b', 'c']
|
711
|
+
@set.merge(['d','c','e'])
|
712
|
+
@set.members.sort.should == ['a', 'b', 'c', 'd', 'e']
|
713
|
+
end
|
714
|
+
|
697
715
|
it "should support sorting" do
|
698
|
-
@set_1 << '
|
699
|
-
@set_2 << 1 << 2 << 3 << 4 << 5
|
700
|
-
@set_3 << 'm_1' << 'm_2'
|
716
|
+
@set_1 << 'c' << 'b' << 'a' << 'e' << 'd'
|
701
717
|
@set_1.sort.should == %w(a b c d e)
|
702
|
-
@set_2.sort.should == %w(1 2 3 4 5)
|
703
|
-
|
704
718
|
@set_1.sort(SORT_ORDER).should == %w(e d c b a)
|
705
|
-
|
719
|
+
|
720
|
+
@set_2 << 2 << 4 << 3 << 1 << 5
|
721
|
+
@set_2.sort.should == %w(1 2 3 4 5)
|
706
722
|
@set_2.sort(SORT_LIMIT).should == %w(3 4)
|
707
723
|
|
724
|
+
@set_3 << 'm_4' << 'm_5' << 'm_1' << 'm_3' << 'm_2'
|
725
|
+
@set_3.sort(:by => 'm_*').should == %w(m_1 m_2 m_3 m_4 m_5)
|
726
|
+
|
708
727
|
val1 = Redis::Value.new('spec/3/sorted')
|
709
728
|
val2 = Redis::Value.new('spec/4/sorted')
|
710
729
|
|
@@ -743,7 +762,7 @@ describe Redis::SortedSet do
|
|
743
762
|
@set_3.clear
|
744
763
|
end
|
745
764
|
|
746
|
-
it "should handle sets of simple values" do
|
765
|
+
it "should handle sorted sets of simple values" do
|
747
766
|
@set.should.be.empty
|
748
767
|
@set['a'] = 11
|
749
768
|
@set['a'] = 21
|
@@ -781,6 +800,7 @@ describe Redis::SortedSet do
|
|
781
800
|
@set['b'] = 5
|
782
801
|
@set['b'] = 6
|
783
802
|
@set.score('b').should == 6
|
803
|
+
@set.score('f').should == nil
|
784
804
|
@set.delete('c')
|
785
805
|
@set.to_s.should == 'a, b'
|
786
806
|
@set.should == ['a','b']
|
@@ -836,7 +856,7 @@ describe Redis::SortedSet do
|
|
836
856
|
@set.size.should == 3
|
837
857
|
end
|
838
858
|
|
839
|
-
it "should support renaming sets" do
|
859
|
+
it "should support renaming sorted sets" do
|
840
860
|
@set.should.be.empty
|
841
861
|
@set['zynga'] = 151
|
842
862
|
@set['playfish'] = 202
|
@@ -504,15 +504,14 @@ describe Redis::Objects do
|
|
504
504
|
@roster.outfielders.should == ['a']
|
505
505
|
@roster.outfielders.get.should == ['a']
|
506
506
|
@roster.outfielders << 'b' << 'b'
|
507
|
-
@roster.outfielders.
|
508
|
-
@roster.outfielders.should == ['a','b']
|
509
|
-
@roster.outfielders.
|
510
|
-
@roster.outfielders.get.should == ['a','b']
|
507
|
+
@roster.outfielders.sort.should == ['a','b']
|
508
|
+
@roster.outfielders.members.sort.should == ['a','b']
|
509
|
+
@roster.outfielders.get.sort.should == ['a','b']
|
511
510
|
@roster.outfielders << 'c'
|
512
511
|
@roster.outfielders.sort.should == ['a','b','c']
|
513
512
|
@roster.outfielders.get.sort.should == ['a','b','c']
|
514
513
|
@roster.outfielders.delete('c')
|
515
|
-
@roster.outfielders.should == ['a','b']
|
514
|
+
@roster.outfielders.sort.should == ['a','b']
|
516
515
|
@roster.outfielders.get.sort.should == ['a','b']
|
517
516
|
@roster.outfielders.length.should == 2
|
518
517
|
@roster.outfielders.size.should == 2
|
@@ -524,9 +523,9 @@ describe Redis::Objects do
|
|
524
523
|
i.should == @roster.outfielders.length
|
525
524
|
|
526
525
|
coll = @roster.outfielders.collect{|st| st}
|
527
|
-
coll.should == ['a','b']
|
528
|
-
@roster.outfielders.should == ['a','b']
|
529
|
-
@roster.outfielders.get.should == ['a','b']
|
526
|
+
coll.sort.should == ['a','b']
|
527
|
+
@roster.outfielders.sort.should == ['a','b']
|
528
|
+
@roster.outfielders.get.sort.should == ['a','b']
|
530
529
|
|
531
530
|
@roster.outfielders << 'c'
|
532
531
|
@roster.outfielders.member?('c').should.be.true
|
@@ -641,15 +640,14 @@ describe Redis::Objects do
|
|
641
640
|
Roster.all_players_online.should == ['a']
|
642
641
|
Roster.all_players_online.get.should == ['a']
|
643
642
|
Roster.all_players_online << 'b' << 'b'
|
644
|
-
Roster.all_players_online.
|
645
|
-
Roster.all_players_online.should == ['a','b']
|
646
|
-
Roster.all_players_online.
|
647
|
-
Roster.all_players_online.get.should == ['a','b']
|
643
|
+
Roster.all_players_online.sort.should == ['a','b']
|
644
|
+
Roster.all_players_online.members.sort.should == ['a','b']
|
645
|
+
Roster.all_players_online.get.sort.should == ['a','b']
|
648
646
|
Roster.all_players_online << 'c'
|
649
647
|
Roster.all_players_online.sort.should == ['a','b','c']
|
650
648
|
Roster.all_players_online.get.sort.should == ['a','b','c']
|
651
649
|
Roster.all_players_online.delete('c')
|
652
|
-
Roster.all_players_online.should == ['a','b']
|
650
|
+
Roster.all_players_online.sort.should == ['a','b']
|
653
651
|
Roster.all_players_online.get.sort.should == ['a','b']
|
654
652
|
Roster.all_players_online.length.should == 2
|
655
653
|
Roster.all_players_online.size.should == 2
|
@@ -661,9 +659,9 @@ describe Redis::Objects do
|
|
661
659
|
i.should == Roster.all_players_online.length
|
662
660
|
|
663
661
|
coll = Roster.all_players_online.collect{|st| st}
|
664
|
-
coll.should == ['a','b']
|
665
|
-
Roster.all_players_online.should == ['a','b']
|
666
|
-
Roster.all_players_online.get.should == ['a','b']
|
662
|
+
coll.sort.should == ['a','b']
|
663
|
+
Roster.all_players_online.sort.should == ['a','b']
|
664
|
+
Roster.all_players_online.get.sort.should == ['a','b']
|
667
665
|
|
668
666
|
Roster.all_players_online << 'c'
|
669
667
|
Roster.all_players_online.member?('c').should.be.true
|
@@ -731,13 +729,14 @@ describe Redis::Objects do
|
|
731
729
|
end
|
732
730
|
|
733
731
|
it "should handle sets of complex data types" do
|
734
|
-
@roster.outfielders << {:a => 1}
|
732
|
+
@roster.outfielders << {:a => 1}
|
733
|
+
@roster.outfielders.members.should == [{:a => 1}]
|
734
|
+
@roster.outfielders << {:b => 2}
|
735
735
|
@roster.outfielders.member?({:b => 2})
|
736
|
-
@roster.outfielders.members.should == [{:b => 2}, {:a => 1}]
|
737
736
|
@roster_1.outfielders << {:a => 1} << {:b => 2}
|
738
737
|
@roster_2.outfielders << {:b => 2} << {:c => 3}
|
739
738
|
(@roster_1.outfielders & @roster_2.outfielders).should == [{:b => 2}]
|
740
|
-
(@roster_1.outfielders | @roster_2.outfielders).should ==
|
739
|
+
#(@roster_1.outfielders | @roster_2.outfielders).members.should ==
|
741
740
|
end
|
742
741
|
|
743
742
|
it "should provide a lock method that accepts a block" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rubygems' # poor people still on 1.8
|
2
|
-
gem 'redis', '>=
|
2
|
+
gem 'redis', '>= 3.0.0'
|
3
3
|
require 'redis'
|
4
4
|
|
5
5
|
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
@@ -28,7 +28,8 @@ at_exit do
|
|
28
28
|
puts "=> Killing #{REDIS_BIN} with pid #{pid}"
|
29
29
|
Process.kill "TERM", pid
|
30
30
|
Process.kill "KILL", pid
|
31
|
-
File.unlink REDIS_PID
|
31
|
+
File.unlink REDIS_PID
|
32
|
+
File.unlink REDIS_DUMP if File.exists? REDIS_DUMP
|
32
33
|
end
|
33
34
|
|
34
35
|
# Grab a global handle
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-objects
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,91 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: redis
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: redis-namespace
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bacon
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: jeweler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: activerecord
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
14
94
|
- !ruby/object:Gem::Dependency
|
15
95
|
name: bacon
|
16
|
-
requirement:
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
17
97
|
none: false
|
18
98
|
requirements:
|
19
99
|
- - ! '>='
|
@@ -21,29 +101,44 @@ dependencies:
|
|
21
101
|
version: '0'
|
22
102
|
type: :development
|
23
103
|
prerelease: false
|
24
|
-
version_requirements:
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
25
110
|
- !ruby/object:Gem::Dependency
|
26
111
|
name: redis-namespace
|
27
|
-
requirement:
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
28
113
|
none: false
|
29
114
|
requirements:
|
30
115
|
- - ! '>='
|
31
116
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
117
|
+
version: 1.2.0
|
33
118
|
type: :development
|
34
119
|
prerelease: false
|
35
|
-
version_requirements:
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.2.0
|
36
126
|
- !ruby/object:Gem::Dependency
|
37
127
|
name: redis
|
38
|
-
requirement:
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
39
129
|
none: false
|
40
130
|
requirements:
|
41
131
|
- - ! '>='
|
42
132
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
133
|
+
version: 3.0.2
|
44
134
|
type: :runtime
|
45
135
|
prerelease: false
|
46
|
-
version_requirements:
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: 3.0.2
|
47
142
|
description: Map Redis types directly to Ruby objects. Works with any class or ORM.
|
48
143
|
email: nate@wiger.org
|
49
144
|
executables: []
|
@@ -53,6 +148,8 @@ extra_rdoc_files:
|
|
53
148
|
files:
|
54
149
|
- ATOMICITY.rdoc
|
55
150
|
- CHANGELOG.rdoc
|
151
|
+
- Gemfile
|
152
|
+
- Gemfile.lock
|
56
153
|
- README.rdoc
|
57
154
|
- Rakefile
|
58
155
|
- VERSION
|
@@ -92,6 +189,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
189
|
- - ! '>='
|
93
190
|
- !ruby/object:Gem::Version
|
94
191
|
version: '0'
|
192
|
+
segments:
|
193
|
+
- 0
|
194
|
+
hash: 4220055926051714921
|
95
195
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
196
|
none: false
|
97
197
|
requirements:
|
@@ -99,9 +199,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
199
|
- !ruby/object:Gem::Version
|
100
200
|
version: '0'
|
101
201
|
requirements:
|
102
|
-
- redis,
|
202
|
+
- redis, v3.0.2 or greater
|
103
203
|
rubyforge_project:
|
104
|
-
rubygems_version: 1.8.
|
204
|
+
rubygems_version: 1.8.24
|
105
205
|
signing_key:
|
106
206
|
specification_version: 3
|
107
207
|
summary: Map Redis types directly to Ruby objects
|