redis-objects 0.4.0 → 0.4.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/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gemspec
2
+ nbproject
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,15 @@
1
1
  = Changelog for Redis::Objects
2
2
 
3
+ == 0.4.1 [Final] (23 August 2010)
4
+
5
+ * Fixes for Ruby 1.8 failures due to missing flatten() [Gabe da Silveira]
6
+
7
+ * Enable subclasses of classes mixing in Redis::Objects to automatically pick up objects from their superclasses [Gabe da Silveira]
8
+
9
+ * Renamed prefix() and field_key() to redis_prefix() and redis_field_key() to prevent gem conflicts [Jason Meinzer]
10
+
11
+ * Fixed a typo in delete_if and added missing test coverage [Julio Capote, Nate Wiger]
12
+
3
13
  == 0.4.0 [Final] (11 August 2010)
4
14
 
5
15
  * Full support for redis hashes via new Redis::Hash class [Julio Capote, Nate Wiger]
data/Rakefile CHANGED
@@ -1,7 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "redis-objects"
8
+ gem.summary = %Q{Map Redis types directly to Ruby objects}
9
+ gem.description = %Q{Map Redis types directly to Ruby objects. Works with any class or ORM.}
10
+ gem.email = "nate@wiger.org"
11
+ gem.homepage = "http://github.com/nateware/redis-objects"
12
+ gem.authors = ["Nate Wiger"]
13
+ gem.add_development_dependency "bacon", ">= 0"
14
+ gem.requirements << 'redis, v2.0.4 or greater'
15
+ gem.add_dependency('redis', '>= 2.0.4')
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ # require 'rake/testtask'
24
+ # Rake::TestTask.new(:spec) do |spec|
25
+ # spec.libs << 'lib' << 'spec'
26
+ # spec.pattern = 'spec/**/*_spec.rb'
27
+ # spec.verbose = true
28
+ # end
1
29
 
2
30
  task :test do
3
- base = File.dirname(__FILE__)
4
- Dir[base + '/spec/*_spec.rb'].each do |f|
5
- sh "ruby #{f}"
31
+ sh "bacon spec/*_spec.rb"
32
+ end
33
+
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |spec|
38
+ spec.libs << 'spec'
39
+ spec.pattern = 'spec/**/*_spec.rb'
40
+ spec.verbose = true
6
41
  end
7
- end
42
+ rescue LoadError
43
+ task :rcov do
44
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
45
+ end
46
+ end
47
+
48
+ task :spec => :check_dependencies
49
+
50
+ task :default => :spec
51
+
52
+ require 'rake/rdoctask'
53
+ Rake::RDocTask.new do |rdoc|
54
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
55
+
56
+ rdoc.rdoc_dir = 'rdoc'
57
+ rdoc.title = "Redis::Objects #{version}"
58
+ rdoc.rdoc_files.include('README*')
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.1
data/lib/redis/hash.rb CHANGED
@@ -11,7 +11,7 @@ class Redis
11
11
  include Redis::Helpers::Serialize
12
12
 
13
13
  attr_reader :key, :redis
14
-
14
+
15
15
  # Needed since Redis::Hash masks bare Hash in redis.rb
16
16
  def self.[](*args)
17
17
  ::Hash[*args]
@@ -71,7 +71,7 @@ class Redis
71
71
  def each(&block)
72
72
  all.each(&block)
73
73
  end
74
-
74
+
75
75
  # Enumerate through each keys. Redis: HKEYS
76
76
  def each_key(&block)
77
77
  keys.each(&block)
@@ -102,9 +102,9 @@ class Redis
102
102
  # Set keys in bulk, takes a hash of field/values {'field1' => 'val1'}. Redis: HMSET
103
103
  def bulk_set(*args)
104
104
  raise ArgumentError, "Argument to bulk_set must be hash of key/value pairs" unless args.last.is_a?(::Hash)
105
- redis.hmset(key, *args.last.flatten)
105
+ redis.hmset(key, *args.last.inject([]){ |arr,kv| arr + kv })
106
106
  end
107
-
107
+
108
108
  # Get keys in bulk, takes an array of fields as arguments. Redis: HMGET
109
109
  def bulk_get(*fields)
110
110
  hsh = {}
@@ -114,12 +114,12 @@ class Redis
114
114
  end
115
115
  hsh
116
116
  end
117
-
117
+
118
118
  # Increment value by integer at field. Redis: HINCRBY
119
119
  def incrby(field, val = 1)
120
120
  redis.hincrby(key, field, val).to_i
121
121
  end
122
- alias_method :incr, :incrby
122
+ alias_method :incr, :incrby
123
123
 
124
124
  end
125
125
  end
data/lib/redis/objects.rb CHANGED
@@ -76,32 +76,41 @@ class Redis
76
76
  module ClassMethods
77
77
  attr_accessor :redis, :redis_objects
78
78
 
79
- # Set the Redis prefix to use. Defaults to model_name
80
- def prefix=(prefix) @prefix = prefix end
81
- def prefix #:nodoc:
82
- @prefix ||= self.name.to_s.
79
+ # Set the Redis redis_prefix to use. Defaults to model_name
80
+ def redis_prefix=(redis_prefix) @redis_prefix = redis_prefix end
81
+ def redis_prefix(klass = self) #:nodoc:
82
+ @redis_prefix ||= klass.name.to_s.
83
83
  sub(%r{(.*::)}, '').
84
84
  gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
85
85
  gsub(/([a-z\d])([A-Z])/,'\1_\2').
86
86
  downcase
87
87
  end
88
88
 
89
- def field_key(name, id='') #:nodoc:
89
+ def redis_field_key(name, id='') #:nodoc:
90
+ klass = first_ancestor_with(name)
90
91
  # This can never ever ever ever change or upgrades will corrupt all data
91
- @redis_objects[name.to_sym][:key] || "#{prefix}:#{id}:#{name}"
92
+ klass.redis_objects[name.to_sym][:key] || "#{redis_prefix(klass)}:#{id}:#{name}"
93
+ end
94
+
95
+ def first_ancestor_with(name)
96
+ if redis_objects && redis_objects.key?(name.to_sym)
97
+ self
98
+ elsif superclass && superclass.respond_to?(:redis_objects)
99
+ superclass.first_ancestor_with(name)
100
+ end
92
101
  end
93
102
  end
94
103
 
95
104
  # Instance methods that appear in your class when you include Redis::Objects.
96
105
  module InstanceMethods
97
106
  def redis() self.class.redis end
98
- def field_key(name) #:nodoc:
99
- # This can never ever ever ever change or upgrades will corrupt all data
100
- if key = self.class.redis_objects[name.to_sym][:key]
107
+ def redis_field_key(name) #:nodoc:
108
+ klass = self.class.first_ancestor_with(name)
109
+ if key = klass.redis_objects[name.to_sym][:key]
101
110
  eval "%(#{key})"
102
111
  else
103
- # don't try to refactor into class field_key because fucks up eval context
104
- "#{self.class.prefix}:#{id}:#{name}"
112
+ # don't try to refactor into class redis_field_key because fucks up eval context
113
+ "#{klass.redis_prefix}:#{id}:#{name}"
105
114
  end
106
115
  end
107
116
  end
@@ -23,10 +23,11 @@ class Redis
23
23
  options[:start] ||= 0
24
24
  options[:type] ||= options[:start] == 0 ? :increment : :decrement
25
25
  @redis_objects[name.to_sym] = options.merge(:type => :counter)
26
+ klass_name = '::' + self.name
26
27
  if options[:global]
27
28
  instance_eval <<-EndMethods
28
29
  def #{name}
29
- @#{name} ||= Redis::Counter.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
30
+ @#{name} ||= Redis::Counter.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
30
31
  end
31
32
  EndMethods
32
33
  class_eval <<-EndMethods
@@ -37,7 +38,7 @@ class Redis
37
38
  else
38
39
  class_eval <<-EndMethods
39
40
  def #{name}
40
- @#{name} ||= Redis::Counter.new(field_key(:#{name}), redis, self.class.redis_objects[:#{name}])
41
+ @#{name} ||= Redis::Counter.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
41
42
  end
42
43
  EndMethods
43
44
  end
@@ -48,7 +49,7 @@ class Redis
48
49
  def get_counter(name, id=nil)
49
50
  verify_counter_defined!(name, id)
50
51
  initialize_counter!(name, id)
51
- redis.get(field_key(name, id)).to_i
52
+ redis.get(redis_field_key(name, id)).to_i
52
53
  end
53
54
 
54
55
  # Increment a counter with the specified name and id. Accepts a block
@@ -56,7 +57,7 @@ class Redis
56
57
  def increment_counter(name, id=nil, by=1, &block)
57
58
  verify_counter_defined!(name, id)
58
59
  initialize_counter!(name, id)
59
- value = redis.incrby(field_key(name, id), by).to_i
60
+ value = redis.incrby(redis_field_key(name, id), by).to_i
60
61
  block_given? ? rewindable_block(:decrement_counter, name, id, value, &block) : value
61
62
  end
62
63
 
@@ -65,7 +66,7 @@ class Redis
65
66
  def decrement_counter(name, id=nil, by=1, &block)
66
67
  verify_counter_defined!(name, id)
67
68
  initialize_counter!(name, id)
68
- value = redis.decrby(field_key(name, id), by).to_i
69
+ value = redis.decrby(redis_field_key(name, id), by).to_i
69
70
  block_given? ? rewindable_block(:increment_counter, name, id, value, &block) : value
70
71
  end
71
72
 
@@ -73,7 +74,7 @@ class Redis
73
74
  def reset_counter(name, id=nil, to=nil)
74
75
  verify_counter_defined!(name, id)
75
76
  to = @redis_objects[name][:start] if to.nil?
76
- redis.set(field_key(name, id), to.to_i)
77
+ redis.set(redis_field_key(name, id), to.to_i)
77
78
  true
78
79
  end
79
80
 
@@ -87,7 +88,7 @@ class Redis
87
88
  end
88
89
 
89
90
  def initialize_counter!(name, id) #:nodoc:
90
- key = field_key(name, id)
91
+ key = redis_field_key(name, id)
91
92
  unless @initialized_counters[key]
92
93
  redis.setnx(key, @redis_objects[name][:start])
93
94
  end
@@ -15,10 +15,11 @@ class Redis
15
15
  # method, so it can be used alongside ActiveRecord, DataMapper, etc.
16
16
  def hash_key(name, options={})
17
17
  @redis_objects[name.to_sym] = options.merge(:type => :dict)
18
+ klass_name = '::' + self.name
18
19
  if options[:global]
19
20
  instance_eval <<-EndMethods
20
21
  def #{name}
21
- @#{name} ||= Redis::Hash.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
22
+ @#{name} ||= Redis::Hash.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
22
23
  end
23
24
  EndMethods
24
25
  class_eval <<-EndMethods
@@ -29,7 +30,7 @@ class Redis
29
30
  else
30
31
  class_eval <<-EndMethods
31
32
  def #{name}
32
- @#{name} ||= Redis::Hash.new(field_key(:#{name}), redis, self.class.redis_objects[:#{name}])
33
+ @#{name} ||= Redis::Hash.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
33
34
  end
34
35
  EndMethods
35
36
  end
@@ -15,10 +15,11 @@ class Redis
15
15
  # method, so it can be used alongside ActiveRecord, DataMapper, etc.
16
16
  def list(name, options={})
17
17
  @redis_objects[name.to_sym] = options.merge(:type => :list)
18
+ klass_name = '::' + self.name
18
19
  if options[:global]
19
20
  instance_eval <<-EndMethods
20
21
  def #{name}
21
- @#{name} ||= Redis::List.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
22
+ @#{name} ||= Redis::List.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
22
23
  end
23
24
  EndMethods
24
25
  class_eval <<-EndMethods
@@ -29,7 +30,7 @@ class Redis
29
30
  else
30
31
  class_eval <<-EndMethods
31
32
  def #{name}
32
- @#{name} ||= Redis::List.new(field_key(:#{name}), redis, self.class.redis_objects[:#{name}])
33
+ @#{name} ||= Redis::List.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
33
34
  end
34
35
  EndMethods
35
36
  end
@@ -18,10 +18,11 @@ class Redis
18
18
  options[:timeout] ||= 5 # seconds
19
19
  lock_name = "#{name}_lock"
20
20
  @redis_objects[lock_name.to_sym] = options.merge(:type => :lock)
21
+ klass_name = '::' + self.name
21
22
  if options[:global]
22
23
  instance_eval <<-EndMethods
23
24
  def #{lock_name}(&block)
24
- @#{lock_name} ||= Redis::Lock.new(field_key(:#{lock_name}), redis, @redis_objects[:#{lock_name}])
25
+ @#{lock_name} ||= Redis::Lock.new(redis_field_key(:#{lock_name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{lock_name}])
25
26
  end
26
27
  EndMethods
27
28
  class_eval <<-EndMethods
@@ -32,7 +33,7 @@ class Redis
32
33
  else
33
34
  class_eval <<-EndMethods
34
35
  def #{lock_name}(&block)
35
- @#{lock_name} ||= Redis::Lock.new(field_key(:#{lock_name}), redis, self.class.redis_objects[:#{lock_name}])
36
+ @#{lock_name} ||= Redis::Lock.new(redis_field_key(:#{lock_name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{lock_name}])
36
37
  end
37
38
  EndMethods
38
39
  end
@@ -45,14 +46,14 @@ class Redis
45
46
  verify_lock_defined!(name)
46
47
  raise ArgumentError, "Missing block to #{self.name}.obtain_lock" unless block_given?
47
48
  lock_name = "#{name}_lock"
48
- Redis::Lock.new(field_key(lock_name, id), redis, @redis_objects[lock_name.to_sym]).lock(&block)
49
+ Redis::Lock.new(redis_field_key(lock_name, id), redis, @redis_objects[lock_name.to_sym]).lock(&block)
49
50
  end
50
51
 
51
52
  # Clear the lock. Use with care - usually only in an Admin page to clear
52
53
  # stale locks (a stale lock should only happen if a server crashes.)
53
54
  def clear_lock(name, id)
54
55
  verify_lock_defined!(name)
55
- redis.del(field_key("#{name}_lock", id))
56
+ redis.del(redis_field_key("#{name}_lock", id))
56
57
  end
57
58
 
58
59
  private
@@ -15,10 +15,11 @@ class Redis
15
15
  # method, so it can be used alongside ActiveRecord, DataMapper, etc.
16
16
  def set(name, options={})
17
17
  @redis_objects[name.to_sym] = options.merge(:type => :set)
18
+ klass_name = '::' + self.name
18
19
  if options[:global]
19
20
  instance_eval <<-EndMethods
20
21
  def #{name}
21
- @#{name} ||= Redis::Set.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
22
+ @#{name} ||= Redis::Set.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
22
23
  end
23
24
  EndMethods
24
25
  class_eval <<-EndMethods
@@ -29,7 +30,7 @@ class Redis
29
30
  else
30
31
  class_eval <<-EndMethods
31
32
  def #{name}
32
- @#{name} ||= Redis::Set.new(field_key(:#{name}), redis, self.class.redis_objects[:#{name}])
33
+ @#{name} ||= Redis::Set.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
33
34
  end
34
35
  EndMethods
35
36
  end
@@ -15,10 +15,11 @@ class Redis
15
15
  # method, so it can be used alongside ActiveRecord, DataMapper, etc.
16
16
  def sorted_set(name, options={})
17
17
  @redis_objects[name.to_sym] = options.merge(:type => :sorted_set)
18
+ klass_name = '::' + self.name
18
19
  if options[:global]
19
20
  instance_eval <<-EndMethods
20
21
  def #{name}
21
- @#{name} ||= Redis::SortedSet.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
22
+ @#{name} ||= Redis::SortedSet.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
22
23
  end
23
24
  EndMethods
24
25
  class_eval <<-EndMethods
@@ -29,7 +30,7 @@ class Redis
29
30
  else
30
31
  class_eval <<-EndMethods
31
32
  def #{name}
32
- @#{name} ||= Redis::SortedSet.new(field_key(:#{name}), redis, self.class.redis_objects[:#{name}])
33
+ @#{name} ||= Redis::SortedSet.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
33
34
  end
34
35
  EndMethods
35
36
  end
@@ -15,10 +15,11 @@ class Redis
15
15
  # method, so it can be used alongside ActiveRecord, DataMapper, etc.
16
16
  def value(name, options={})
17
17
  @redis_objects[name.to_sym] = options.merge(:type => :value)
18
+ klass_name = '::' + self.name
18
19
  if options[:global]
19
20
  instance_eval <<-EndMethods
20
21
  def #{name}
21
- @#{name} ||= Redis::Value.new(field_key(:#{name}), redis, @redis_objects[:#{name}])
22
+ @#{name} ||= Redis::Value.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
22
23
  end
23
24
  def #{name}=(value)
24
25
  #{name}.value = value
@@ -35,7 +36,7 @@ class Redis
35
36
  else
36
37
  class_eval <<-EndMethods
37
38
  def #{name}
38
- @#{name} ||= Redis::Value.new(field_key(:#{name}), redis, self.class.redis_objects[:#{name}])
39
+ @#{name} ||= Redis::Value.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
39
40
  end
40
41
  def #{name}=(value)
41
42
  #{name}.value = value
data/lib/redis/set.rb CHANGED
@@ -45,10 +45,10 @@ class Redis
45
45
  end
46
46
 
47
47
  # Delete if matches block
48
- def delete_if(&blk)
48
+ def delete_if(&block)
49
49
  res = false
50
50
  redis.smembers(key).each do |m|
51
- if blk.call(from_redis(m))
51
+ if block.call(from_redis(m))
52
52
  res = redis.srem(key, m)
53
53
  end
54
54
  end
@@ -144,10 +144,10 @@ class Redis
144
144
  end
145
145
 
146
146
  # Delete element if it matches block
147
- def delete_if(&blocK)
147
+ def delete_if(&block)
148
148
  raise ArgumentError, "Missing block to SortedSet#delete_if" unless block_given?
149
149
  res = false
150
- redis.zrevrange(key, 0, -1).each do |m|
150
+ redis.zrange(key, 0, -1).each do |m|
151
151
  if block.call(from_redis(m))
152
152
  res = redis.zrem(key, m)
153
153
  end
@@ -501,6 +501,8 @@ describe Redis::Set do
501
501
  coll = @set.select{|st| st == 'c'}
502
502
  coll.should == ['c']
503
503
  @set.sort.should == ['a','b','c']
504
+ @set.delete_if{|m| m == 'c'}
505
+ @set.sort.should == ['a','b']
504
506
  end
505
507
 
506
508
  it "should handle set intersections, unions, and diffs" do
@@ -654,61 +656,11 @@ describe Redis::SortedSet do
654
656
  @set.delete('c')
655
657
  @set.length.should == 4
656
658
  @set.size.should == 4
659
+
660
+ @set.delete_if{|m| m == 'b'}
661
+ @set.size.should == 3
657
662
  end
658
663
 
659
- =begin
660
-
661
- # Not until Redis 1.3.5 with hashes
662
- it "Redis 1.3.5: should handle set intersections, unions, and diffs" do
663
- @set_1['a'] = 5
664
- @set_2['b'] = 18
665
- @set_2['c'] = 12
666
-
667
- @set_2['a'] = 10
668
- @set_2['b'] = 15
669
- @set_2['c'] = 15
670
-
671
- (@set_1 & @set_2).sort.should == ['c','d','e']
672
-
673
- @set_1 << 'a' << 'b' << 'c' << 'd' << 'e'
674
- @set_2 << 'c' << 'd' << 'e' << 'f' << 'g'
675
- @set_3 << 'a' << 'd' << 'g' << 'l' << 'm'
676
- @set_1.sort.should == %w(a b c d e)
677
- @set_2.sort.should == %w(c d e f g)
678
- @set_3.sort.should == %w(a d g l m)
679
- (@set_1 & @set_2).sort.should == ['c','d','e']
680
- @set_1.intersection(@set_2).sort.should == ['c','d','e']
681
- @set_1.intersection(@set_2, @set_3).sort.should == ['d']
682
- @set_1.intersect(@set_2).sort.should == ['c','d','e']
683
- @set_1.inter(@set_2, @set_3).sort.should == ['d']
684
- @set_1.interstore(INTERSTORE_KEY, @set_2).should == 3
685
- @set_1.redis.smembers(INTERSTORE_KEY).sort.should == ['c','d','e']
686
- @set_1.interstore(INTERSTORE_KEY, @set_2, @set_3).should == 1
687
- @set_1.redis.smembers(INTERSTORE_KEY).sort.should == ['d']
688
-
689
- (@set_1 | @set_2).sort.should == ['a','b','c','d','e','f','g']
690
- (@set_1 + @set_2).sort.should == ['a','b','c','d','e','f','g']
691
- @set_1.union(@set_2).sort.should == ['a','b','c','d','e','f','g']
692
- @set_1.union(@set_2, @set_3).sort.should == ['a','b','c','d','e','f','g','l','m']
693
- @set_1.unionstore(UNIONSTORE_KEY, @set_2).should == 7
694
- @set_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g']
695
- @set_1.unionstore(UNIONSTORE_KEY, @set_2, @set_3).should == 9
696
- @set_1.redis.smembers(UNIONSTORE_KEY).sort.should == ['a','b','c','d','e','f','g','l','m']
697
-
698
- (@set_1 ^ @set_2).sort.should == ["a", "b"]
699
- (@set_1 - @set_2).sort.should == ["a", "b"]
700
- (@set_2 - @set_1).sort.should == ["f", "g"]
701
- @set_1.difference(@set_2).sort.should == ["a", "b"]
702
- @set_1.diff(@set_2).sort.should == ["a", "b"]
703
- @set_1.difference(@set_2, @set_3).sort.should == ['b']
704
- @set_1.diffstore(DIFFSTORE_KEY, @set_2).should == 2
705
- @set_1.redis.smembers(DIFFSTORE_KEY).sort.should == ['a','b']
706
- @set_1.diffstore(DIFFSTORE_KEY, @set_2, @set_3).should == 1
707
- @set_1.redis.smembers(DIFFSTORE_KEY).sort.should == ['b']
708
- end
709
-
710
- =end
711
-
712
664
  it "should support renaming sets" do
713
665
  @set.should.be.empty
714
666
  @set['zynga'] = 151
@@ -35,6 +35,18 @@ class Roster
35
35
  def max_pitchers; 3; end
36
36
  end
37
37
 
38
+ class VanillaRoster < Roster
39
+ # No explicit Redis::Objects
40
+ end
41
+
42
+ class CustomRoster < Roster
43
+ include Redis::Objects
44
+
45
+ counter :basic # Override
46
+ counter :special # New
47
+ end
48
+
49
+
38
50
  describe Redis::Objects do
39
51
  before do
40
52
  @roster = Roster.new
@@ -44,6 +56,9 @@ describe Redis::Objects do
44
56
  @roster_2 = Roster.new(2)
45
57
  @roster_3 = Roster.new(3)
46
58
 
59
+ @vanilla_roster = VanillaRoster.new
60
+ @custom_roster = CustomRoster.new
61
+
47
62
  @roster.available_slots.reset
48
63
  @roster.pitchers.reset
49
64
  @roster.basic.reset
@@ -69,6 +84,9 @@ describe Redis::Objects do
69
84
  @roster.all_player_stats.clear
70
85
  @roster.total_wins.clear
71
86
  @roster.my_rank.clear
87
+
88
+ @custom_roster.basic.reset
89
+ @custom_roster.special.reset
72
90
  end
73
91
 
74
92
  it "should provide a connection method" do
@@ -690,4 +708,44 @@ describe Redis::Objects do
690
708
  error.should.not.be.nil
691
709
  error.should.be.kind_of(Redis::Lock::LockTimeout)
692
710
  end
711
+
712
+ it "should pick up objects from superclass automatically" do
713
+ @vanilla_roster.available_slots.should.be.kind_of(Redis::Counter)
714
+ @vanilla_roster.pitchers.should.be.kind_of(Redis::Counter)
715
+ @vanilla_roster.basic.should.be.kind_of(Redis::Counter)
716
+ @vanilla_roster.resort_lock.should.be.kind_of(Redis::Lock)
717
+ @vanilla_roster.starting_pitcher.should.be.kind_of(Redis::Value)
718
+ @vanilla_roster.player_stats.should.be.kind_of(Redis::List)
719
+ @vanilla_roster.outfielders.should.be.kind_of(Redis::Set)
720
+ @vanilla_roster.rank.should.be.kind_of(Redis::SortedSet)
721
+
722
+ # custom keys
723
+ @vanilla_roster.player_totals.should.be.kind_of(Redis::Counter)
724
+ @vanilla_roster.all_player_stats.should.be.kind_of(Redis::List)
725
+ @vanilla_roster.total_wins.should.be.kind_of(Redis::Set)
726
+ @vanilla_roster.my_rank.should.be.kind_of(Redis::Value)
727
+ @vanilla_roster.weird_key.should.be.kind_of(Redis::Value)
728
+
729
+ # globals via class
730
+ @vanilla_roster.total_players_online.should.be.kind_of(Redis::Counter)
731
+ @vanilla_roster.all_player_stats.should.be.kind_of(Redis::List)
732
+ @vanilla_roster.all_players_online.should.be.kind_of(Redis::Set)
733
+ @vanilla_roster.last_player.should.be.kind_of(Redis::Value)
734
+
735
+ VanillaRoster.total_players_online.should.be.kind_of(Redis::Counter)
736
+ VanillaRoster.all_player_stats.should.be.kind_of(Redis::List)
737
+ VanillaRoster.all_players_online.should.be.kind_of(Redis::Set)
738
+ VanillaRoster.last_player.should.be.kind_of(Redis::Value)
739
+ end
740
+
741
+ it "should allow subclass overrides of the same redis object" do
742
+ @roster.basic.should == 0
743
+ @custom_roster.basic.increment.should == 1
744
+ @roster2.basic.should == 0
745
+ CustomRoster.new.basic.should == 1
746
+ end
747
+
748
+ it "should handle new subclass objects" do
749
+ @custom_roster.special.increment.should == 1
750
+ end
693
751
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,8 @@
1
+ require 'rubygems' # poor people still on 1.8
2
+
1
3
  $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
2
4
  require 'redis'
3
5
 
4
- require 'rubygems' # poor people still on 1.8
5
6
  require 'bacon'
6
7
  Bacon.summary_at_exit
7
8
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-objects
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 13
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 4
8
- - 0
9
- version: 0.4.0
9
+ - 1
10
+ version: 0.4.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Nate Wiger
@@ -14,23 +15,39 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-08-11 00:00:00 -07:00
18
+ date: 2010-08-23 00:00:00 -07:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- name: redis
22
+ name: bacon
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: redis
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
24
40
  requirements:
25
41
  - - ">="
26
42
  - !ruby/object:Gem::Version
43
+ hash: 7
27
44
  segments:
28
45
  - 2
29
46
  - 0
30
47
  - 4
31
48
  version: 2.0.4
32
49
  type: :runtime
33
- version_requirements: *id001
50
+ version_requirements: *id002
34
51
  description: Map Redis types directly to Ruby objects. Works with any class or ORM.
35
52
  email: nate@wiger.org
36
53
  executables: []
@@ -38,11 +55,14 @@ executables: []
38
55
  extensions: []
39
56
 
40
57
  extra_rdoc_files:
58
+ - README.rdoc
59
+ files:
60
+ - .gitignore
41
61
  - ATOMICITY.rdoc
42
62
  - CHANGELOG.rdoc
43
- - Rakefile
44
63
  - README.rdoc
45
- files:
64
+ - Rakefile
65
+ - VERSION
46
66
  - lib/redis/base_object.rb
47
67
  - lib/redis/counter.rb
48
68
  - lib/redis/hash.rb
@@ -50,6 +70,7 @@ files:
50
70
  - lib/redis/helpers/serialize.rb
51
71
  - lib/redis/list.rb
52
72
  - lib/redis/lock.rb
73
+ - lib/redis/objects.rb
53
74
  - lib/redis/objects/counters.rb
54
75
  - lib/redis/objects/hashes.rb
55
76
  - lib/redis/objects/lists.rb
@@ -57,47 +78,48 @@ files:
57
78
  - lib/redis/objects/sets.rb
58
79
  - lib/redis/objects/sorted_sets.rb
59
80
  - lib/redis/objects/values.rb
60
- - lib/redis/objects.rb
61
81
  - lib/redis/set.rb
62
82
  - lib/redis/sorted_set.rb
63
83
  - lib/redis/value.rb
84
+ - redis-objects.gemspec
64
85
  - spec/redis_objects_instance_spec.rb
65
86
  - spec/redis_objects_model_spec.rb
66
87
  - spec/spec_helper.rb
67
- - ATOMICITY.rdoc
68
- - CHANGELOG.rdoc
69
- - Rakefile
70
- - README.rdoc
71
88
  has_rdoc: true
72
89
  homepage: http://github.com/nateware/redis-objects
73
90
  licenses: []
74
91
 
75
92
  post_install_message:
76
93
  rdoc_options:
77
- - --title
78
- - Redis::Objects -- Use Redis types as Ruby objects
94
+ - --charset=UTF-8
79
95
  require_paths:
80
96
  - lib
81
97
  required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
82
99
  requirements:
83
100
  - - ">="
84
101
  - !ruby/object:Gem::Version
102
+ hash: 3
85
103
  segments:
86
104
  - 0
87
105
  version: "0"
88
106
  required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
89
108
  requirements:
90
109
  - - ">="
91
110
  - !ruby/object:Gem::Version
111
+ hash: 3
92
112
  segments:
93
113
  - 0
94
114
  version: "0"
95
115
  requirements:
96
116
  - redis, v2.0.4 or greater
97
- rubyforge_project: redis-objects
98
- rubygems_version: 1.3.6
117
+ rubyforge_project:
118
+ rubygems_version: 1.3.7
99
119
  signing_key:
100
120
  specification_version: 3
101
- summary: Maps Redis types to Ruby objects
102
- test_files: []
103
-
121
+ summary: Map Redis types directly to Ruby objects
122
+ test_files:
123
+ - spec/redis_objects_instance_spec.rb
124
+ - spec/redis_objects_model_spec.rb
125
+ - spec/spec_helper.rb