redis-objects 0.1.0 → 0.1.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/README.rdoc +54 -19
- data/lib/redis/counter.rb +2 -3
- data/lib/redis/list.rb +40 -30
- data/lib/redis/lock.rb +2 -2
- data/lib/redis/objects/counters.rb +1 -1
- data/lib/redis/objects/lists.rb +1 -1
- data/lib/redis/objects/locks.rb +1 -1
- data/lib/redis/objects/sets.rb +25 -0
- data/lib/redis/objects/values.rb +1 -1
- data/lib/redis/set.rb +68 -0
- data/lib/redis/value.rb +2 -2
- data/spec/redis_objects_model_spec.rb +100 -0
- metadata +4 -4
    
        data/README.rdoc
    CHANGED
    
    | @@ -4,13 +4,12 @@ This is *not* an ORM.  People that are wrapping ORM's around Redis are missing | |
| 4 4 | 
             
            the point.
         | 
| 5 5 |  | 
| 6 6 | 
             
            The killer feature of Redis that it allows you to perform atomic operations
         | 
| 7 | 
            -
            on _individual_ data structures, like counters, lists, and sets | 
| 8 | 
            -
            *with* your existing ActiveRecord/DataMapper/etc models, or in classes that have
         | 
| 7 | 
            +
            on _individual_ data structures, like counters, lists, and sets. You can then use
         | 
| 8 | 
            +
            these *with* your existing ActiveRecord/DataMapper/etc models, or in classes that have
         | 
| 9 9 | 
             
            nothing to do with an ORM or even a database. That's where this gem comes in.
         | 
| 10 10 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
            games; for a fun rant on the topic, see
         | 
| 11 | 
            +
            This gem originally arose out of a need for high-concurrency atomic operations;
         | 
| 12 | 
            +
            for a fun rant on the topic, see
         | 
| 14 13 | 
             
            {ATOMICITY}[http://github.com/nateware/redis-objects/blob/master/ATOMICITY.rdoc],
         | 
| 15 14 | 
             
            or scroll down to "Atomicity" in this README.
         | 
| 16 15 |  | 
| @@ -23,6 +22,8 @@ by using +new+ with the type of data structure you want to create. | |
| 23 22 | 
             
                gem tumble
         | 
| 24 23 | 
             
                gem install redis-objects
         | 
| 25 24 |  | 
| 25 | 
            +
            == Example 1: Class Usage
         | 
| 26 | 
            +
             | 
| 26 27 | 
             
            === Initialization
         | 
| 27 28 |  | 
| 28 29 | 
             
                # If on Rails, config/initializers/redis.rb is a good place for this
         | 
| @@ -30,42 +31,76 @@ by using +new+ with the type of data structure you want to create. | |
| 30 31 | 
             
                require 'redis/objects'
         | 
| 31 32 | 
             
                Redis::Objects.redis = Redis.new(:host => 127.0.0.1, :port => 6379)
         | 
| 32 33 |  | 
| 33 | 
            -
             | 
| 34 | 
            +
            === Model Class
         | 
| 34 35 |  | 
| 35 | 
            -
             | 
| 36 | 
            +
            Include in any type of class:
         | 
| 36 37 |  | 
| 37 38 | 
             
                class Team < ActiveRecord::Base
         | 
| 38 39 | 
             
                  include Redis::Objects
         | 
| 39 40 |  | 
| 40 | 
            -
                  counter : | 
| 41 | 
            -
                  counter : | 
| 42 | 
            -
                  counter : | 
| 41 | 
            +
                  counter :hits
         | 
| 42 | 
            +
                  counter :runs
         | 
| 43 | 
            +
                  counter :outs
         | 
| 44 | 
            +
                  counter :inning, :start => 1
         | 
| 43 45 | 
             
                  list :on_base
         | 
| 44 46 | 
             
                  set :outfielders
         | 
| 45 | 
            -
                  value : | 
| 47 | 
            +
                  value :at_bat
         | 
| 46 48 | 
             
                end
         | 
| 47 49 |  | 
| 48 | 
            -
            Familiar Ruby operations Just Work:
         | 
| 50 | 
            +
            Familiar Ruby array operations Just Work (TM):
         | 
| 49 51 |  | 
| 50 52 | 
             
                @team = Team.find(1)
         | 
| 51 53 | 
             
                @team.on_base << 'player1'
         | 
| 52 54 | 
             
                @team.on_base << 'player2'
         | 
| 53 | 
            -
                 | 
| 55 | 
            +
                @team.on_base << 'player3'
         | 
| 56 | 
            +
                puts @team.on_base    # ['player1', 'player2']
         | 
| 54 57 | 
             
                @team.on_base.pop
         | 
| 58 | 
            +
                @team.on_base.shift
         | 
| 59 | 
            +
                @team.on_base.length  # 1
         | 
| 60 | 
            +
                @team.on_base.delete('player3')
         | 
| 61 | 
            +
                
         | 
| 62 | 
            +
            Sets work like the Ruby {Set}[http://ruby-doc.org/core/classes/Set.html] class:
         | 
| 63 | 
            +
                
         | 
| 64 | 
            +
                @team.outfielders['1b'] = 'outfielder1'
         | 
| 65 | 
            +
                @team.outfielders['lf'] = 'outfielder3'
         | 
| 66 | 
            +
                @team.outfielders['lf'] = 'outfielder2'
         | 
| 67 | 
            +
                @team.outfielders.keys
         | 
| 68 | 
            +
                @team.outfielders.each do |position,player|
         | 
| 69 | 
            +
                  puts "#{player} is playing #{position}"
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
                position = @team.outfielders.detect{|pos,of| of == 'outfielder3'}
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            Note counters cannot be assigned to, only incremented/decremented:
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                @team.hits.increment  # or incr
         | 
| 76 | 
            +
                @team.hits.decrement  # or decr
         | 
| 77 | 
            +
                @team.runs = 4        # exception
         | 
| 78 | 
            +
                @team.runs += 1       # exception
         | 
| 55 79 |  | 
| 56 | 
            -
             | 
| 80 | 
            +
            It would be cool to get that last one working, but Ruby's implementation of +=
         | 
| 81 | 
            +
            is problematic.
         | 
| 57 82 |  | 
| 58 | 
            -
             | 
| 59 | 
            -
                @team.drafted_players.decrement  # or decr
         | 
| 60 | 
            -
                @team.drafted_players = 4   # exception
         | 
| 61 | 
            -
                @team.drafted_players += 1  # exception
         | 
| 83 | 
            +
            == Example 2: Instance Usage
         | 
| 62 84 |  | 
| 63 | 
            -
             | 
| 85 | 
            +
            Each data type can be used independently.
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            === Initialization
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            Can follow the +$redis+ global variable pattern:
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                $redis = Redis.new(:host => 'localhost', :port => 6379)
         | 
| 92 | 
            +
                @value = Redis::Value.new('myvalue')
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            Or can pass the handle into the new method:
         | 
| 95 | 
            +
                
         | 
| 96 | 
            +
                redis  = Redis.new(:host => 'localhost', :port => 6379)
         | 
| 97 | 
            +
                @value = Redis::Value.new('myvalue', redis)
         | 
| 64 98 |  | 
| 65 99 | 
             
            === Counters
         | 
| 66 100 |  | 
| 67 101 | 
             
                @counter = Redis::Counter.new('counter_name')
         | 
| 68 102 | 
             
                @counter.increment
         | 
| 103 | 
            +
                @counter.decrement
         | 
| 69 104 | 
             
                puts @counter
         | 
| 70 105 | 
             
                puts @counter.get  # force re-fetch
         | 
| 71 106 |  | 
    
        data/lib/redis/counter.rb
    CHANGED
    
    | @@ -8,12 +8,11 @@ class Redis | |
| 8 8 | 
             
              #
         | 
| 9 9 | 
             
              class Counter
         | 
| 10 10 | 
             
                attr_reader :key, :options, :redis
         | 
| 11 | 
            -
                def initialize(key, options={})
         | 
| 11 | 
            +
                def initialize(key, redis=$redis, options={})
         | 
| 12 12 | 
             
                  @key = key
         | 
| 13 | 
            +
                  @redis = redis
         | 
| 13 14 | 
             
                  @options = options
         | 
| 14 | 
            -
                  @redis = options[:redis] || $redis || Redis::Objects.redis
         | 
| 15 15 | 
             
                  @options[:start] ||= 0
         | 
| 16 | 
            -
                  @options[:type]  ||= @options[:start] == 0 ? :increment : :decrement
         | 
| 17 16 | 
             
                  @redis.setnx(key, @options[:start]) unless @options[:start] == 0 || @options[:init] === false
         | 
| 18 17 | 
             
                end
         | 
| 19 18 |  | 
    
        data/lib/redis/list.rb
    CHANGED
    
    | @@ -4,71 +4,77 @@ class Redis | |
| 4 4 | 
             
              # behave as much like Ruby arrays as possible.
         | 
| 5 5 | 
             
              #
         | 
| 6 6 | 
             
              class List
         | 
| 7 | 
            +
                require 'enumerator'
         | 
| 8 | 
            +
                include Enumerable
         | 
| 9 | 
            +
             | 
| 7 10 | 
             
                attr_reader :key, :options, :redis
         | 
| 8 | 
            -
                def initialize(key, options={})
         | 
| 11 | 
            +
                def initialize(key, redis=$redis, options={})
         | 
| 9 12 | 
             
                  @key = key
         | 
| 13 | 
            +
                  @redis = redis
         | 
| 10 14 | 
             
                  @options = options
         | 
| 11 | 
            -
                  @redis   = options[:redis] || $redis || Redis::Objects.redis
         | 
| 12 | 
            -
                  @options[:start] ||= 0
         | 
| 13 | 
            -
                  @options[:type]  ||= @options[:start] == 0 ? :increment : :decrement
         | 
| 14 | 
            -
                  @redis.setnx(key, @options[:start]) unless @options[:start] == 0 || @options[:init] === false
         | 
| 15 15 | 
             
                end
         | 
| 16 | 
            -
             | 
| 16 | 
            +
                
         | 
| 17 | 
            +
                # Works like push.  Can chain together: list << 'a' << 'b'
         | 
| 17 18 | 
             
                def <<(value)
         | 
| 18 19 | 
             
                  push(value)
         | 
| 20 | 
            +
                  self  # for << 'a' << 'b'
         | 
| 19 21 | 
             
                end
         | 
| 20 | 
            -
             | 
| 22 | 
            +
             | 
| 23 | 
            +
                # Add a member to the end of the list. Redis: RPUSH
         | 
| 21 24 | 
             
                def push(value)
         | 
| 22 25 | 
             
                  redis.rpush(key, value)
         | 
| 23 | 
            -
                  @values << value
         | 
| 24 26 | 
             
                end
         | 
| 25 27 |  | 
| 28 | 
            +
                # Remove a member from the end of the list. Redis: RPOP
         | 
| 26 29 | 
             
                def pop
         | 
| 27 30 | 
             
                  redis.rpop(key)
         | 
| 28 | 
            -
                  @values.pop
         | 
| 29 31 | 
             
                end
         | 
| 30 32 |  | 
| 33 | 
            +
                # Add a member to the start of the list. Redis: LPUSH
         | 
| 31 34 | 
             
                def unshift(value)
         | 
| 32 35 | 
             
                  redis.lpush(key, value)
         | 
| 33 | 
            -
                  @values.unshift value
         | 
| 34 36 | 
             
                end
         | 
| 35 37 |  | 
| 38 | 
            +
                # Remove a member from the start of the list. Redis: LPOP
         | 
| 36 39 | 
             
                def shift
         | 
| 37 40 | 
             
                  redis.lpop(key)
         | 
| 38 41 | 
             
                end
         | 
| 39 42 |  | 
| 43 | 
            +
                # Return all values in the list. Redis: LRANGE(0,-1)
         | 
| 40 44 | 
             
                def values
         | 
| 41 | 
            -
                   | 
| 45 | 
            +
                  range(0, -1)
         | 
| 42 46 | 
             
                end
         | 
| 47 | 
            +
                alias_method :get, :values
         | 
| 43 48 |  | 
| 44 | 
            -
                 | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
                 | 
| 48 | 
            -
             | 
| 49 | 
            -
                def get
         | 
| 50 | 
            -
                  @values = range(0, -1)
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
                
         | 
| 53 | 
            -
                def [](index)
         | 
| 54 | 
            -
                  case index
         | 
| 55 | 
            -
                  when Range
         | 
| 49 | 
            +
                # Same functionality as Ruby arrays.  If a single number is given, return
         | 
| 50 | 
            +
                # just the element at that index using Redis: LINDEX. Otherwise, return
         | 
| 51 | 
            +
                # a range of values using Redis: LRANGE.
         | 
| 52 | 
            +
                def [](index, length=nil)
         | 
| 53 | 
            +
                  if index.is_a? Range
         | 
| 56 54 | 
             
                    range(index.first, index.last)
         | 
| 55 | 
            +
                  elsif length
         | 
| 56 | 
            +
                    range(index, length)
         | 
| 57 57 | 
             
                  else
         | 
| 58 | 
            -
                     | 
| 58 | 
            +
                    at(index)
         | 
| 59 59 | 
             
                  end
         | 
| 60 60 | 
             
                end
         | 
| 61 61 |  | 
| 62 62 | 
             
                def delete(name, count=0)
         | 
| 63 | 
            -
                  redis.lrem( | 
| 63 | 
            +
                  redis.lrem(key, count, name)  # weird api
         | 
| 64 | 
            +
                  get
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def each(&block)
         | 
| 68 | 
            +
                  values.each(&block)
         | 
| 64 69 | 
             
                end
         | 
| 65 70 |  | 
| 66 71 | 
             
                def range(start_index, end_index)
         | 
| 67 72 | 
             
                  redis.lrange(key, start_index, end_index)
         | 
| 68 73 | 
             
                end
         | 
| 69 | 
            -
             | 
| 74 | 
            +
             | 
| 75 | 
            +
                # Return the value at the given index.
         | 
| 70 76 | 
             
                def at(index)
         | 
| 71 | 
            -
                  redis. | 
| 77 | 
            +
                  redis.lindex(key, index)
         | 
| 72 78 | 
             
                end
         | 
| 73 79 |  | 
| 74 80 | 
             
                def last
         | 
| @@ -80,16 +86,20 @@ class Redis | |
| 80 86 | 
             
                end
         | 
| 81 87 |  | 
| 82 88 | 
             
                def length
         | 
| 83 | 
            -
                  redis. | 
| 89 | 
            +
                  redis.llen(key)
         | 
| 84 90 | 
             
                end
         | 
| 85 91 | 
             
                alias_method :size, :length
         | 
| 86 92 |  | 
| 87 93 | 
             
                def empty?
         | 
| 88 | 
            -
                   | 
| 94 | 
            +
                  length == 0
         | 
| 89 95 | 
             
                end
         | 
| 90 | 
            -
             | 
| 96 | 
            +
             
         | 
| 91 97 | 
             
                def ==(x)
         | 
| 92 98 | 
             
                  values == x
         | 
| 93 99 | 
             
                end
         | 
| 100 | 
            +
                
         | 
| 101 | 
            +
                def to_s
         | 
| 102 | 
            +
                  values.join(', ')
         | 
| 103 | 
            +
                end
         | 
| 94 104 | 
             
              end
         | 
| 95 105 | 
             
            end
         | 
    
        data/lib/redis/lock.rb
    CHANGED
    
    | @@ -10,11 +10,11 @@ class Redis | |
| 10 10 | 
             
                class LockTimeout < StandardError; end #:nodoc:
         | 
| 11 11 |  | 
| 12 12 | 
             
                attr_reader :key, :options, :redis
         | 
| 13 | 
            -
                def initialize(key, options={})
         | 
| 13 | 
            +
                def initialize(key, redis=$redis, options={})
         | 
| 14 14 | 
             
                  @key = key
         | 
| 15 | 
            +
                  @redis = redis
         | 
| 15 16 | 
             
                  @options = options
         | 
| 16 17 | 
             
                  @options[:timeout] ||= 5
         | 
| 17 | 
            -
                  @redis = options[:redis] || $redis || Redis::Objects.redis
         | 
| 18 18 | 
             
                  @redis.setnx(key, @options[:start]) unless @options[:start] == 0 || @options[:init] === false
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| @@ -24,7 +24,7 @@ class Redis | |
| 24 24 | 
             
                      @counters[name] = options
         | 
| 25 25 | 
             
                      class_eval <<-EndMethods
         | 
| 26 26 | 
             
                        def #{name}
         | 
| 27 | 
            -
                          @#{name} ||= Redis::Counter.new(field_key(:#{name}), self.class.counters[:#{name}] | 
| 27 | 
            +
                          @#{name} ||= Redis::Counter.new(field_key(:#{name}), redis, self.class.counters[:#{name}])
         | 
| 28 28 | 
             
                        end
         | 
| 29 29 | 
             
                      EndMethods
         | 
| 30 30 | 
             
                    end
         | 
    
        data/lib/redis/objects/lists.rb
    CHANGED
    
    | @@ -20,7 +20,7 @@ class Redis | |
| 20 20 | 
             
                      @lists[name] = options
         | 
| 21 21 | 
             
                      class_eval <<-EndMethods
         | 
| 22 22 | 
             
                        def #{name}
         | 
| 23 | 
            -
                          @#{name} ||= Redis::List.new(field_key(:#{name}), self.class.lists[:#{name}] | 
| 23 | 
            +
                          @#{name} ||= Redis::List.new(field_key(:#{name}), redis, self.class.lists[:#{name}])
         | 
| 24 24 | 
             
                        end
         | 
| 25 25 | 
             
                      EndMethods
         | 
| 26 26 | 
             
                    end
         | 
    
        data/lib/redis/objects/locks.rb
    CHANGED
    
    | @@ -22,7 +22,7 @@ class Redis | |
| 22 22 | 
             
                      @locks[name] = options
         | 
| 23 23 | 
             
                      class_eval <<-EndMethods
         | 
| 24 24 | 
             
                        def #{name}_lock(&block)
         | 
| 25 | 
            -
                          @#{name}_lock ||= Redis::Lock.new(field_key(:#{name}_lock), self.class.locks[:#{name}] | 
| 25 | 
            +
                          @#{name}_lock ||= Redis::Lock.new(field_key(:#{name}_lock), redis, self.class.locks[:#{name}])
         | 
| 26 26 | 
             
                        end
         | 
| 27 27 | 
             
                      EndMethods
         | 
| 28 28 | 
             
                    end
         | 
    
        data/lib/redis/objects/sets.rb
    CHANGED
    
    | @@ -4,6 +4,31 @@ require 'redis/set' | |
| 4 4 | 
             
            class Redis
         | 
| 5 5 | 
             
              module Objects
         | 
| 6 6 | 
             
                module Sets
         | 
| 7 | 
            +
                  def self.included(klass)
         | 
| 8 | 
            +
                    klass.instance_variable_set('@sets', {})
         | 
| 9 | 
            +
                    klass.send :include, InstanceMethods
         | 
| 10 | 
            +
                    klass.extend ClassMethods
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  # Class methods that appear in your class when you include Redis::Objects.
         | 
| 14 | 
            +
                  module ClassMethods
         | 
| 15 | 
            +
                    attr_reader :sets
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    # Define a new list.  It will function like a regular instance
         | 
| 18 | 
            +
                    # method, so it can be used alongside ActiveRecord, DataMapper, etc.
         | 
| 19 | 
            +
                    def set(name, options={})
         | 
| 20 | 
            +
                      @sets[name] = options
         | 
| 21 | 
            +
                      class_eval <<-EndMethods
         | 
| 22 | 
            +
                        def #{name}
         | 
| 23 | 
            +
                          @#{name} ||= Redis::Set.new(field_key(:#{name}), redis, self.class.sets[:#{name}])
         | 
| 24 | 
            +
                        end
         | 
| 25 | 
            +
                      EndMethods
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  # Instance methods that appear in your class when you include Redis::Objects.
         | 
| 30 | 
            +
                  module InstanceMethods
         | 
| 31 | 
            +
                  end
         | 
| 7 32 | 
             
                end
         | 
| 8 33 | 
             
              end
         | 
| 9 34 | 
             
            end
         | 
    
        data/lib/redis/objects/values.rb
    CHANGED
    
    | @@ -20,7 +20,7 @@ class Redis | |
| 20 20 | 
             
                      @values[name] = options
         | 
| 21 21 | 
             
                      class_eval <<-EndMethods
         | 
| 22 22 | 
             
                        def #{name}
         | 
| 23 | 
            -
                          @#{name} ||= Redis::Value.new(field_key(:#{name}), self.class.values[:#{name}] | 
| 23 | 
            +
                          @#{name} ||= Redis::Value.new(field_key(:#{name}), redis, self.class.values[:#{name}])
         | 
| 24 24 | 
             
                        end
         | 
| 25 25 | 
             
                        def #{name}=(value)
         | 
| 26 26 | 
             
                          #{name}.value = value
         | 
    
        data/lib/redis/set.rb
    CHANGED
    
    | @@ -3,5 +3,73 @@ class Redis | |
| 3 3 | 
             
              # Class representing a set.
         | 
| 4 4 | 
             
              #
         | 
| 5 5 | 
             
              class Set
         | 
| 6 | 
            +
                require 'enumerator'
         | 
| 7 | 
            +
                include Enumerable
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                attr_reader :key, :options, :redis
         | 
| 10 | 
            +
                def initialize(key, redis=$redis, options={})
         | 
| 11 | 
            +
                  @key = key
         | 
| 12 | 
            +
                  @redis = redis
         | 
| 13 | 
            +
                  @options = options
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                # Works like add.  Can chain together: list << 'a' << 'b'
         | 
| 17 | 
            +
                def <<(value)
         | 
| 18 | 
            +
                  add(value)
         | 
| 19 | 
            +
                  self  # for << 'a' << 'b'
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                
         | 
| 22 | 
            +
                # Add the specified value to the set only if it does not exist already.
         | 
| 23 | 
            +
                # Redis: SADD
         | 
| 24 | 
            +
                def add(value)
         | 
| 25 | 
            +
                  redis.sadd(key, value)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # Return all members in the set.  Redis: SMEMBERS
         | 
| 29 | 
            +
                def members
         | 
| 30 | 
            +
                  redis.smembers(key)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                alias_method :get, :members
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                # Returns true if the specified value is in the set.  Redis: SISMEMBER
         | 
| 35 | 
            +
                def member?(value)
         | 
| 36 | 
            +
                  redis.sismember(key, value)
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                # Delete the value from the set.  Redis: SREM
         | 
| 40 | 
            +
                def delete(name)
         | 
| 41 | 
            +
                  redis.srem(key, name)
         | 
| 42 | 
            +
                  get
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                # Wipe the set entirely.  Redis: DEL
         | 
| 46 | 
            +
                def clear
         | 
| 47 | 
            +
                  redis.del(key)
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                # Iterate through each member of the set.  Redis::Objects mixes in Enumerable,
         | 
| 51 | 
            +
                # so you can also use familiar methods like +collect+, +detect+, and so forth.
         | 
| 52 | 
            +
                def each(&block)
         | 
| 53 | 
            +
                  members.each(&block)
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # The number of members in the set. Aliased as size. Redis: SCARD
         | 
| 57 | 
            +
                def length
         | 
| 58 | 
            +
                  redis.scard(key)
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
                alias_method :size, :length
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                # Returns true if the set has no members. Redis: SCARD == 0
         | 
| 63 | 
            +
                def empty?
         | 
| 64 | 
            +
                  length == 0
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def ==(x)
         | 
| 68 | 
            +
                  members == x
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
                
         | 
| 71 | 
            +
                def to_s
         | 
| 72 | 
            +
                  members.join(', ')
         | 
| 73 | 
            +
                end
         | 
| 6 74 | 
             
              end
         | 
| 7 75 | 
             
            end
         | 
    
        data/lib/redis/value.rb
    CHANGED
    
    | @@ -4,10 +4,10 @@ class Redis | |
| 4 4 | 
             
              #
         | 
| 5 5 | 
             
              class Value
         | 
| 6 6 | 
             
                attr_reader :key, :options, :redis
         | 
| 7 | 
            -
                def initialize(key, options={})
         | 
| 7 | 
            +
                def initialize(key, redis=$redis, options={})
         | 
| 8 8 | 
             
                  @key = key
         | 
| 9 | 
            +
                  @redis = redis
         | 
| 9 10 | 
             
                  @options = options
         | 
| 10 | 
            -
                  @redis   = options[:redis] || $redis || Redis::Objects.redis
         | 
| 11 11 | 
             
                  @redis.setnx(key, @options[:default]) if @options[:default]
         | 
| 12 12 | 
             
                end
         | 
| 13 13 |  | 
| @@ -10,6 +10,7 @@ class Roster | |
| 10 10 | 
             
              lock :resort, :timeout => 2
         | 
| 11 11 | 
             
              value :starting_pitcher
         | 
| 12 12 | 
             
              list :player_stats
         | 
| 13 | 
            +
              set :outfielders
         | 
| 13 14 |  | 
| 14 15 | 
             
              def initialize(id=1) @id = id end
         | 
| 15 16 | 
             
              def id; @id; end
         | 
| @@ -29,6 +30,7 @@ describe Redis::Objects do | |
| 29 30 | 
             
                @roster.resort_lock.clear
         | 
| 30 31 | 
             
                @roster.starting_pitcher.delete
         | 
| 31 32 | 
             
                @roster.player_stats.clear
         | 
| 33 | 
            +
                @roster.outfielders.clear
         | 
| 32 34 | 
             
              end
         | 
| 33 35 |  | 
| 34 36 | 
             
              it "should provide a connection method" do
         | 
| @@ -254,6 +256,104 @@ describe Redis::Objects do | |
| 254 256 | 
             
                @roster.player_stats.should be_empty
         | 
| 255 257 | 
             
                @roster.player_stats << 'a'
         | 
| 256 258 | 
             
                @roster.player_stats.should == ['a']
         | 
| 259 | 
            +
                @roster.player_stats.get.should == ['a']
         | 
| 260 | 
            +
                @roster.player_stats.unshift 'b'
         | 
| 261 | 
            +
                @roster.player_stats.to_s.should == 'b, a'
         | 
| 262 | 
            +
                @roster.player_stats.should == ['b','a']
         | 
| 263 | 
            +
                @roster.player_stats.get.should == ['b','a']
         | 
| 264 | 
            +
                @roster.player_stats.push 'c'
         | 
| 265 | 
            +
                @roster.player_stats.should == ['b','a','c']
         | 
| 266 | 
            +
                @roster.player_stats.get.should == ['b','a','c']
         | 
| 267 | 
            +
                @roster.player_stats << 'd'
         | 
| 268 | 
            +
                @roster.player_stats.should == ['b','a','c','d']
         | 
| 269 | 
            +
                @roster.player_stats[1].should == 'a'
         | 
| 270 | 
            +
                @roster.player_stats[0].should == 'b'
         | 
| 271 | 
            +
                @roster.player_stats[2].should == 'c'
         | 
| 272 | 
            +
                @roster.player_stats[3].should == 'd'
         | 
| 273 | 
            +
                @roster.player_stats.pop
         | 
| 274 | 
            +
                @roster.player_stats[0].should == @roster.player_stats.at(0)
         | 
| 275 | 
            +
                @roster.player_stats[1].should == @roster.player_stats.at(1)
         | 
| 276 | 
            +
                @roster.player_stats[2].should == @roster.player_stats.at(2)
         | 
| 277 | 
            +
                @roster.player_stats.should == ['b','a','c']
         | 
| 278 | 
            +
                @roster.player_stats.get.should == ['b','a','c']
         | 
| 279 | 
            +
                @roster.player_stats.shift
         | 
| 280 | 
            +
                @roster.player_stats.should == ['a','c']
         | 
| 281 | 
            +
                @roster.player_stats.get.should == ['a','c']
         | 
| 282 | 
            +
                @roster.player_stats << 'e' << 'f' << 'e'
         | 
| 283 | 
            +
                @roster.player_stats.should == ['a','c','e','f','e']
         | 
| 284 | 
            +
                @roster.player_stats.get.should == ['a','c','e','f','e']
         | 
| 285 | 
            +
                @roster.player_stats.delete('e')
         | 
| 286 | 
            +
                @roster.player_stats.should == ['a','c','f']
         | 
| 287 | 
            +
                @roster.player_stats.get.should == ['a','c','f']
         | 
| 288 | 
            +
                @roster.player_stats << 'j'
         | 
| 289 | 
            +
                @roster.player_stats.should == ['a','c','f','j']
         | 
| 290 | 
            +
                @roster.player_stats[0..2].should == ['a','c','f']
         | 
| 291 | 
            +
                @roster.player_stats[1, 3].should == ['c','f','j']
         | 
| 292 | 
            +
                @roster.player_stats.length.should == 4
         | 
| 293 | 
            +
                @roster.player_stats.size.should == 4
         | 
| 294 | 
            +
                @roster.player_stats.should == ['a','c','f','j']
         | 
| 295 | 
            +
                @roster.player_stats.get.should == ['a','c','f','j']
         | 
| 296 | 
            +
             | 
| 297 | 
            +
                i = -1
         | 
| 298 | 
            +
                @roster.player_stats.each do |st|
         | 
| 299 | 
            +
                  st.should == @roster.player_stats[i += 1]
         | 
| 300 | 
            +
                end
         | 
| 301 | 
            +
                @roster.player_stats.should == ['a','c','f','j']
         | 
| 302 | 
            +
                @roster.player_stats.get.should == ['a','c','f','j']
         | 
| 303 | 
            +
             | 
| 304 | 
            +
                @roster.player_stats.each_with_index do |st,i|
         | 
| 305 | 
            +
                  st.should == @roster.player_stats[i]
         | 
| 306 | 
            +
                end
         | 
| 307 | 
            +
                @roster.player_stats.should == ['a','c','f','j']
         | 
| 308 | 
            +
                @roster.player_stats.get.should == ['a','c','f','j']
         | 
| 309 | 
            +
             | 
| 310 | 
            +
                coll = @roster.player_stats.collect{|st| st}
         | 
| 311 | 
            +
                coll.should == ['a','c','f','j']
         | 
| 312 | 
            +
                @roster.player_stats.should == ['a','c','f','j']
         | 
| 313 | 
            +
                @roster.player_stats.get.should == ['a','c','f','j']
         | 
| 314 | 
            +
             | 
| 315 | 
            +
                @roster.player_stats << 'a'
         | 
| 316 | 
            +
                coll = @roster.player_stats.select{|st| st == 'a'}
         | 
| 317 | 
            +
                coll.should == ['a','a']
         | 
| 318 | 
            +
                @roster.player_stats.should == ['a','c','f','j','a']
         | 
| 319 | 
            +
                @roster.player_stats.get.should == ['a','c','f','j','a']
         | 
| 320 | 
            +
              end
         | 
| 321 | 
            +
             | 
| 322 | 
            +
              it "should handle sets of simple values" do
         | 
| 323 | 
            +
                @roster.outfielders.should be_empty
         | 
| 324 | 
            +
                @roster.outfielders << 'a' << 'a' << 'a'
         | 
| 325 | 
            +
                @roster.outfielders.should == ['a']
         | 
| 326 | 
            +
                @roster.outfielders.get.should == ['a']
         | 
| 327 | 
            +
                @roster.outfielders << 'b' << 'b'
         | 
| 328 | 
            +
                @roster.outfielders.to_s.should == 'a, b'
         | 
| 329 | 
            +
                @roster.outfielders.should == ['a','b']
         | 
| 330 | 
            +
                @roster.outfielders.members.should == ['a','b']
         | 
| 331 | 
            +
                @roster.outfielders.get.should == ['a','b']
         | 
| 332 | 
            +
                @roster.outfielders << 'c'
         | 
| 333 | 
            +
                @roster.outfielders.sort.should == ['a','b','c']
         | 
| 334 | 
            +
                @roster.outfielders.get.sort.should == ['a','b','c']
         | 
| 335 | 
            +
                @roster.outfielders.delete('c')
         | 
| 336 | 
            +
                @roster.outfielders.should == ['a','b']
         | 
| 337 | 
            +
                @roster.outfielders.get.sort.should == ['a','b']
         | 
| 338 | 
            +
                @roster.outfielders.length.should == 2
         | 
| 339 | 
            +
                @roster.outfielders.size.should == 2
         | 
| 340 | 
            +
                
         | 
| 341 | 
            +
                i = 0
         | 
| 342 | 
            +
                @roster.outfielders.each do |st|
         | 
| 343 | 
            +
                  i += 1
         | 
| 344 | 
            +
                end
         | 
| 345 | 
            +
                i.should == @roster.outfielders.length
         | 
| 346 | 
            +
             | 
| 347 | 
            +
                coll = @roster.outfielders.collect{|st| st}
         | 
| 348 | 
            +
                coll.should == ['a','b']
         | 
| 349 | 
            +
                @roster.outfielders.should == ['a','b']
         | 
| 350 | 
            +
                @roster.outfielders.get.should == ['a','b']
         | 
| 351 | 
            +
             | 
| 352 | 
            +
                @roster.outfielders << 'c'
         | 
| 353 | 
            +
                @roster.outfielders.member? 'c'
         | 
| 354 | 
            +
                coll = @roster.outfielders.select{|st| st == 'c'}
         | 
| 355 | 
            +
                coll.should == ['c']
         | 
| 356 | 
            +
                @roster.outfielders.sort.should == ['a','b','c']
         | 
| 257 357 | 
             
              end
         | 
| 258 358 |  | 
| 259 359 | 
             
              it "should provide a lock method that accepts a block" do
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: redis-objects
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - Nate Wiger
         | 
| @@ -9,11 +9,11 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2009-11- | 
| 12 | 
            +
            date: 2009-11-26 00:00:00 -08:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: []
         | 
| 15 15 |  | 
| 16 | 
            -
            description: Redis | 
| 16 | 
            +
            description: Map Redis types directly to Ruby objects. Works with any class or ORM.
         | 
| 17 17 | 
             
            email: nate@wiger.org
         | 
| 18 18 | 
             
            executables: []
         | 
| 19 19 |  | 
| @@ -68,6 +68,6 @@ rubyforge_project: redis-objects | |
| 68 68 | 
             
            rubygems_version: 1.3.5
         | 
| 69 69 | 
             
            signing_key: 
         | 
| 70 70 | 
             
            specification_version: 3
         | 
| 71 | 
            -
            summary:  | 
| 71 | 
            +
            summary: Maps Redis types to Ruby objects
         | 
| 72 72 | 
             
            test_files: []
         | 
| 73 73 |  |