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 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
- self.class.field_key(name, id)
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}, ''), redis, @redis_objects[:#{name}])
29
+ @#{name} ||= Redis::Counter.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
30
30
  end
31
31
  EndMethods
32
32
  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 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}, ''), redis, @redis_objects[:#{name}])
21
+ @#{name} ||= Redis::List.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
22
22
  end
23
23
  EndMethods
24
24
  class_eval <<-EndMethods
@@ -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
- @redis_objects[name] = options.merge(:type => :lock)
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 #{name}_lock(&block)
23
- @#{name} ||= Redis::Lock.new(field_key(:#{name}_lock, ''), redis, @redis_objects[:#{name}])
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 #{name}_lock(&block)
28
- self.class.#{name}(block)
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 #{name}_lock(&block)
34
- @#{name} ||= Redis::Lock.new(field_key(:#{name}_lock), redis, self.class.redis_objects[:#{name}])
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 = field_key("#{name}_lock", id)
47
- Redis::Lock.new(lock_name, redis, self.redis_objects[name]).lock(&block)
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
- lock_name = field_key("#{name}_lock", id)
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
- raise Redis::Objects::UndefinedLock, "Undefined lock :#{name} for class #{self.name}" unless @redis_objects.has_key?(name)
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
@@ -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}, ''), redis, @redis_objects[:#{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}, ''), redis, @redis_objects[:#{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
 
@@ -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}, ''), redis, @redis_objects[:#{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
@@ -14,7 +14,7 @@ class Redis
14
14
 
15
15
  # Create a new SortedSet.
16
16
  def initialize(key, *args)
17
- @key = key
17
+ @key = key.is_a?(Array) ? key.flatten.join(':') : key
18
18
  @options = args.last.is_a?(Hash) ? args.pop : {}
19
19
  @redis = args.first || $redis
20
20
  end
@@ -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
- - 0
9
- version: 0.3.0
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-04-14 00:00:00 -07:00
17
+ date: 2010-06-01 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency