redis-objects 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -5
- data/lib/redis/objects.rb +12 -6
- data/lib/redis/objects/counters.rb +2 -2
- data/lib/redis/objects/lists.rb +2 -2
- data/lib/redis/objects/locks.rb +15 -13
- data/lib/redis/objects/sets.rb +2 -2
- data/lib/redis/objects/sorted_sets.rb +2 -3
- data/lib/redis/objects/values.rb +2 -2
- data/lib/redis/set.rb +16 -4
- data/lib/redis/sorted_set.rb +1 -1
- data/spec/redis_objects_model_spec.rb +30 -2
- metadata +3 -3
data/CHANGELOG.rdoc
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
= Changelog for Redis::Objects
|
2
2
|
|
3
|
+
== 0.3.1 [Final] (1 June 2010)
|
4
|
+
|
5
|
+
* Integrated fixes for sorted_set deletions from capotej (Julio Capote)
|
6
|
+
|
3
7
|
== 0.3.0 [Final] (14 April 2010)
|
4
8
|
|
5
|
-
* Due to Ruby 1.9 bugs and performance considerations, marshaling of
|
6
|
-
data types is now OFF by default. You must say :marshal => true for
|
7
|
-
any objects that you want serialization enabled on. [Nate Wiger]
|
9
|
+
* 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]
|
8
10
|
|
9
|
-
* Sorted Set class changed slightly due to feedback. You can now get
|
10
|
-
an individual element back via @set['item'] since it acts like a Hash.
|
11
|
+
* 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.
|
11
12
|
|
12
13
|
== 0.2.4 [Final] (9 April 2010)*
|
13
14
|
|
data/lib/redis/objects.rb
CHANGED
@@ -13,7 +13,7 @@ class Redis
|
|
13
13
|
# include Redis::Objects
|
14
14
|
#
|
15
15
|
# counter :joined_players
|
16
|
-
# counter :active_players
|
16
|
+
# counter :active_players, :key => 'game:#{id}:act_plyr'
|
17
17
|
# lock :archive_game
|
18
18
|
# set :player_ids
|
19
19
|
# end
|
@@ -83,18 +83,24 @@ class Redis
|
|
83
83
|
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
84
84
|
downcase
|
85
85
|
end
|
86
|
-
|
87
|
-
def field_key(name, id) #:nodoc:
|
88
|
-
"#{prefix}:#{id}:#{name}"
|
89
|
-
end
|
90
86
|
|
87
|
+
def field_key(name, id='') #:nodoc:
|
88
|
+
# This can never ever ever ever change or upgrades will corrupt all data
|
89
|
+
@redis_objects[name.to_sym][:key] || "#{prefix}:#{id}:#{name}"
|
90
|
+
end
|
91
91
|
end
|
92
92
|
|
93
93
|
# Instance methods that appear in your class when you include Redis::Objects.
|
94
94
|
module InstanceMethods
|
95
95
|
def redis() self.class.redis end
|
96
96
|
def field_key(name) #:nodoc:
|
97
|
-
|
97
|
+
# This can never ever ever ever change or upgrades will corrupt all data
|
98
|
+
if key = self.class.redis_objects[name.to_sym][:key]
|
99
|
+
eval "%(#{key})"
|
100
|
+
else
|
101
|
+
# don't try to refactor into class field_key because fucks up eval context
|
102
|
+
"#{self.class.prefix}:#{id}:#{name}"
|
103
|
+
end
|
98
104
|
end
|
99
105
|
end
|
100
106
|
end
|
@@ -22,11 +22,11 @@ class Redis
|
|
22
22
|
def counter(name, options={})
|
23
23
|
options[:start] ||= 0
|
24
24
|
options[:type] ||= options[:start] == 0 ? :increment : :decrement
|
25
|
-
@redis_objects[name] = options.merge(:type => :counter)
|
25
|
+
@redis_objects[name.to_sym] = options.merge(:type => :counter)
|
26
26
|
if options[:global]
|
27
27
|
instance_eval <<-EndMethods
|
28
28
|
def #{name}
|
29
|
-
@#{name} ||= Redis::Counter.new(field_key(:#{name}
|
29
|
+
@#{name} ||= Redis::Counter.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
|
30
30
|
end
|
31
31
|
EndMethods
|
32
32
|
class_eval <<-EndMethods
|
data/lib/redis/objects/lists.rb
CHANGED
@@ -14,11 +14,11 @@ class Redis
|
|
14
14
|
# Define a new list. It will function like a regular instance
|
15
15
|
# method, so it can be used alongside ActiveRecord, DataMapper, etc.
|
16
16
|
def list(name, options={})
|
17
|
-
@redis_objects[name] = options.merge(:type => :list)
|
17
|
+
@redis_objects[name.to_sym] = options.merge(:type => :list)
|
18
18
|
if options[:global]
|
19
19
|
instance_eval <<-EndMethods
|
20
20
|
def #{name}
|
21
|
-
@#{name} ||= Redis::List.new(field_key(:#{name}
|
21
|
+
@#{name} ||= Redis::List.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
|
22
22
|
end
|
23
23
|
EndMethods
|
24
24
|
class_eval <<-EndMethods
|
data/lib/redis/objects/locks.rb
CHANGED
@@ -16,22 +16,23 @@ class Redis
|
|
16
16
|
# so it can be used alongside ActiveRecord/DataMapper, etc.
|
17
17
|
def lock(name, options={})
|
18
18
|
options[:timeout] ||= 5 # seconds
|
19
|
-
|
19
|
+
lock_name = "#{name}_lock"
|
20
|
+
@redis_objects[lock_name.to_sym] = options.merge(:type => :lock)
|
20
21
|
if options[:global]
|
21
22
|
instance_eval <<-EndMethods
|
22
|
-
def #{
|
23
|
-
@#{
|
23
|
+
def #{lock_name}(&block)
|
24
|
+
@#{lock_name} ||= Redis::Lock.new(field_key(:#{lock_name}), redis, @redis_objects[:#{lock_name}])
|
24
25
|
end
|
25
26
|
EndMethods
|
26
27
|
class_eval <<-EndMethods
|
27
|
-
def #{
|
28
|
-
self.class.#{
|
28
|
+
def #{lock_name}(&block)
|
29
|
+
self.class.#{lock_name}(block)
|
29
30
|
end
|
30
31
|
EndMethods
|
31
32
|
else
|
32
33
|
class_eval <<-EndMethods
|
33
|
-
def #{
|
34
|
-
@#{
|
34
|
+
def #{lock_name}(&block)
|
35
|
+
@#{lock_name} ||= Redis::Lock.new(field_key(:#{lock_name}), redis, self.class.redis_objects[:#{lock_name}])
|
35
36
|
end
|
36
37
|
EndMethods
|
37
38
|
end
|
@@ -43,22 +44,23 @@ class Redis
|
|
43
44
|
def obtain_lock(name, id, &block)
|
44
45
|
verify_lock_defined!(name)
|
45
46
|
raise ArgumentError, "Missing block to #{self.name}.obtain_lock" unless block_given?
|
46
|
-
lock_name =
|
47
|
-
Redis::Lock.new(lock_name, redis,
|
47
|
+
lock_name = "#{name}_lock"
|
48
|
+
Redis::Lock.new(field_key(lock_name, id), redis, @redis_objects[lock_name.to_sym]).lock(&block)
|
48
49
|
end
|
49
50
|
|
50
51
|
# Clear the lock. Use with care - usually only in an Admin page to clear
|
51
52
|
# stale locks (a stale lock should only happen if a server crashes.)
|
52
53
|
def clear_lock(name, id)
|
53
54
|
verify_lock_defined!(name)
|
54
|
-
|
55
|
-
redis.del(lock_name)
|
55
|
+
redis.del(field_key("#{name}_lock", id))
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
private
|
59
59
|
|
60
60
|
def verify_lock_defined!(name)
|
61
|
-
|
61
|
+
unless @redis_objects.has_key?("#{name}_lock".to_sym)
|
62
|
+
raise Redis::Objects::UndefinedLock, "Undefined lock :#{name} for class #{self.name}"
|
63
|
+
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
end
|
data/lib/redis/objects/sets.rb
CHANGED
@@ -14,11 +14,11 @@ class Redis
|
|
14
14
|
# Define a new list. It will function like a regular instance
|
15
15
|
# method, so it can be used alongside ActiveRecord, DataMapper, etc.
|
16
16
|
def set(name, options={})
|
17
|
-
@redis_objects[name] = options.merge(:type => :set)
|
17
|
+
@redis_objects[name.to_sym] = options.merge(:type => :set)
|
18
18
|
if options[:global]
|
19
19
|
instance_eval <<-EndMethods
|
20
20
|
def #{name}
|
21
|
-
@#{name} ||= Redis::Set.new(field_key(:#{name}
|
21
|
+
@#{name} ||= Redis::Set.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
|
22
22
|
end
|
23
23
|
EndMethods
|
24
24
|
class_eval <<-EndMethods
|
@@ -14,11 +14,11 @@ class Redis
|
|
14
14
|
# Define a new list. It will function like a regular instance
|
15
15
|
# method, so it can be used alongside ActiveRecord, DataMapper, etc.
|
16
16
|
def sorted_set(name, options={})
|
17
|
-
@redis_objects[name] = options.merge(:type => :sorted_set)
|
17
|
+
@redis_objects[name.to_sym] = options.merge(:type => :sorted_set)
|
18
18
|
if options[:global]
|
19
19
|
instance_eval <<-EndMethods
|
20
20
|
def #{name}
|
21
|
-
@#{name} ||= Redis::SortedSet.new(field_key(:#{name}
|
21
|
+
@#{name} ||= Redis::SortedSet.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
|
22
22
|
end
|
23
23
|
EndMethods
|
24
24
|
class_eval <<-EndMethods
|
@@ -33,7 +33,6 @@ class Redis
|
|
33
33
|
end
|
34
34
|
EndMethods
|
35
35
|
end
|
36
|
-
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
data/lib/redis/objects/values.rb
CHANGED
@@ -14,11 +14,11 @@ class Redis
|
|
14
14
|
# Define a new simple value. It will function like a regular instance
|
15
15
|
# method, so it can be used alongside ActiveRecord, DataMapper, etc.
|
16
16
|
def value(name, options={})
|
17
|
-
@redis_objects[name] = options.merge(:type => :value)
|
17
|
+
@redis_objects[name.to_sym] = options.merge(:type => :value)
|
18
18
|
if options[:global]
|
19
19
|
instance_eval <<-EndMethods
|
20
20
|
def #{name}
|
21
|
-
@#{name} ||= Redis::Value.new(field_key(:#{name}
|
21
|
+
@#{name} ||= Redis::Value.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
|
22
22
|
end
|
23
23
|
def #{name}=(value)
|
24
24
|
#{name}.value = value
|
data/lib/redis/set.rb
CHANGED
@@ -42,12 +42,23 @@ class Redis
|
|
42
42
|
redis.sismember(key, to_redis(value))
|
43
43
|
end
|
44
44
|
alias_method :include?, :member?
|
45
|
-
|
45
|
+
|
46
46
|
# Delete the value from the set. Redis: SREM
|
47
47
|
def delete(value)
|
48
|
-
redis.srem(key, value)
|
48
|
+
redis.srem(key, to_redis(value))
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
|
+
# Delete if matches block
|
52
|
+
def delete_if(&blk)
|
53
|
+
res = false
|
54
|
+
redis.smembers(key).each do |m|
|
55
|
+
if blk.call(from_redis(m))
|
56
|
+
res = redis.srem(key, m)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
res
|
60
|
+
end
|
61
|
+
|
51
62
|
# Iterate through each member of the set. Redis::Objects mixes in Enumerable,
|
52
63
|
# so you can also use familiar methods like +collect+, +detect+, and so forth.
|
53
64
|
def each(&block)
|
@@ -131,6 +142,7 @@ class Redis
|
|
131
142
|
redis.scard(key)
|
132
143
|
end
|
133
144
|
alias_method :size, :length
|
145
|
+
alias_method :count, :length
|
134
146
|
|
135
147
|
# Returns true if the set has no members. Redis: SCARD == 0
|
136
148
|
def empty?
|
@@ -153,4 +165,4 @@ class Redis
|
|
153
165
|
end
|
154
166
|
|
155
167
|
end
|
156
|
-
end
|
168
|
+
end
|
data/lib/redis/sorted_set.rb
CHANGED
@@ -19,9 +19,17 @@ class Roster
|
|
19
19
|
list :all_player_stats, :global => true
|
20
20
|
set :all_players_online, :global => true
|
21
21
|
value :last_player, :global => true
|
22
|
+
|
23
|
+
# custom keys
|
24
|
+
counter :player_totals, :key => 'players/#{username}/total'
|
25
|
+
list :all_player_stats, :key => 'players:all_stats'
|
26
|
+
set :total_wins, :key => 'players:#{id}:all_stats'
|
27
|
+
value :my_rank, :key => 'players:my_rank:#{username}'
|
28
|
+
value :weird_key, :key => 'players:weird_key:#{raise}', :global => true
|
22
29
|
|
23
30
|
def initialize(id=1) @id = id end
|
24
31
|
def id; @id; end
|
32
|
+
def username; "user#{id}"; end
|
25
33
|
def max_pitchers; 3; end
|
26
34
|
end
|
27
35
|
|
@@ -49,17 +57,38 @@ describe Redis::Objects do
|
|
49
57
|
@roster.redis.del(UNIONSTORE_KEY)
|
50
58
|
@roster.redis.del(INTERSTORE_KEY)
|
51
59
|
@roster.redis.del(DIFFSTORE_KEY)
|
52
|
-
|
60
|
+
|
53
61
|
Roster.total_players_online.reset
|
54
62
|
Roster.all_player_stats.clear
|
55
63
|
Roster.all_players_online.clear
|
56
64
|
Roster.last_player.delete
|
65
|
+
Roster.weird_key.clear
|
66
|
+
|
67
|
+
@roster.player_totals.clear
|
68
|
+
@roster.all_player_stats.clear
|
69
|
+
@roster.total_wins.clear
|
70
|
+
@roster.my_rank.clear
|
57
71
|
end
|
58
72
|
|
59
73
|
it "should provide a connection method" do
|
60
74
|
Roster.redis.should == Redis::Objects.redis
|
61
75
|
# Roster.redis.should be_kind_of(Redis)
|
62
76
|
end
|
77
|
+
|
78
|
+
it "should support custom key names" do
|
79
|
+
@roster.player_totals.incr
|
80
|
+
@roster.redis.get('players/user1/total').should == '1'
|
81
|
+
@roster.redis.get('players/#{username}/total').should be_nil
|
82
|
+
@roster.all_player_stats << 'a'
|
83
|
+
@roster.redis.lindex('players:all_stats', 0).should == 'a'
|
84
|
+
@roster.total_wins << 'a'
|
85
|
+
@roster.redis.smembers('players:1:all_stats').should == ['a']
|
86
|
+
@roster.redis.smembers('players:#{id}:all_stats').should == []
|
87
|
+
@roster.my_rank = 'a'
|
88
|
+
@roster.redis.get('players:my_rank:user1').should == 'a'
|
89
|
+
Roster.weird_key = 'tuka'
|
90
|
+
Roster.redis.get('players:weird_key:#{raise}').should == 'tuka'
|
91
|
+
end
|
63
92
|
|
64
93
|
it "should create counter accessors" do
|
65
94
|
[:available_slots, :pitchers, :basic].each do |m|
|
@@ -648,5 +677,4 @@ describe Redis::Objects do
|
|
648
677
|
error.should_not be_nil
|
649
678
|
error.should be_kind_of(Redis::Lock::LockTimeout)
|
650
679
|
end
|
651
|
-
|
652
680
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 1
|
9
|
+
version: 0.3.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nate Wiger
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-01 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|