redis-objects 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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