redis-objects 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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