redis-objects 0.5.3 → 0.6.0
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.
- 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
|