redis-objects 0.1.0 → 0.1.2

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 CHANGED
@@ -1,16 +1,15 @@
1
- = Redis::Objects - Lightweight, atomic object layer around redis-rb
1
+ = Redis::Objects - Map Redis types directly to Ruby objects
2
2
 
3
3
  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, that you can use
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
- This gem originally arose out of a need for high-concurrency operations for online
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,51 +31,117 @@ 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
- == Examples
34
+ === Model Class
34
35
 
35
- === Model Class Usage
36
+ Include in any type of class:
36
37
 
37
38
  class Team < ActiveRecord::Base
38
39
  include Redis::Objects
39
40
 
40
- counter :drafted_players
41
- counter :active_players
42
- counter :total_online_players, :global => true
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 :coach
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
- puts @team.on_base # ['player1', 'player2']
55
+ @team.on_base << 'player3'
56
+ @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 << 'outfielder1' << 'outfielder1'
65
+ @team.outfielders << 'outfielder2'
66
+ @team.outfielders # ['outfielder1', 'outfielder2']
67
+ @team.outfielders.each do |player|
68
+ puts player
69
+ end
70
+ player = @team.outfielders.detect{|of| of == 'outfielder2'}
55
71
 
56
- With one purposeful exception - counters cannot be set, only incremented/decremented:
72
+ Note counters cannot be assigned to, only incremented/decremented:
57
73
 
58
- @team.drafted_players.increment # or incr
59
- @team.drafted_players.decrement # or decr
60
- @team.drafted_players = 4 # exception
61
- @team.drafted_players += 1 # exception
74
+ @team.hits.increment # or incr
75
+ @team.hits.decrement # or decr
76
+ @team.runs = 4 # exception
77
+ @team.runs += 1 # exception
78
+
79
+ It would be cool to get that last one working, but Ruby's implementation of +=
80
+ is problematic.
81
+
82
+ == Example 2: Instance Usage
83
+
84
+ Each data type can be used independently.
85
+
86
+ === Initialization
62
87
 
63
- === Instance Usage
88
+ Can follow the +$redis+ global variable pattern:
89
+
90
+ $redis = Redis.new(:host => 'localhost', :port => 6379)
91
+ @value = Redis::Value.new('myvalue')
92
+
93
+ Or can pass the handle into the new method:
94
+
95
+ redis = Redis.new(:host => 'localhost', :port => 6379)
96
+ @value = Redis::Value.new('myvalue', redis)
64
97
 
65
98
  === Counters
66
99
 
67
100
  @counter = Redis::Counter.new('counter_name')
68
101
  @counter.increment
69
- puts @counter
70
- puts @counter.get # force re-fetch
102
+ @counter.decrement
103
+ puts @counter.value
104
+ @counter.increment do |val|
105
+ raise "Full" if val > MAX_VAL # rewind counter
106
+ end
107
+
108
+ See the section on "Atomicity" for cool uses of atomic counter blocks.
71
109
 
72
110
  === Lists
73
111
 
112
+ These work just like Ruby arrays:
113
+
74
114
  @list = Redis::List.new('list_name')
75
115
  @list << 'a'
76
116
  @list << 'b'
77
- puts @list
117
+ @list.include? 'c' # false
118
+ @list.values # ['a','b']
119
+ @list.shift
120
+ @list.pop
121
+ @list.clear
122
+ # etc
123
+
124
+ === Sets
125
+
126
+ Sets work like the Ruby {Set}[http://ruby-doc.org/core/classes/Set.html] class:
127
+
128
+ @set = Redis::Set.new('set_name')
129
+ @set << 'a'
130
+ @set << 'b'
131
+ @set << 'a'
132
+ @set.member? 'c' # false
133
+ @set.members # ['a','b']
134
+ @set.each do |member|
135
+ puts member
136
+ end
137
+ @set.clear
138
+ # etc
139
+
140
+ === Values
141
+
142
+ @value = Redis::Value.new('value_name')
143
+ @value.value = 'a'
144
+ @value.delete
78
145
 
79
146
  == Atomicity
80
147
 
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,92 +4,119 @@ 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
- @values ||= get
45
+ range(0, -1)
42
46
  end
47
+ alias_method :get, :values
43
48
 
44
- def value=(val)
45
- redis.set(key, val)
46
- @values = val
47
- end
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
- range(index, index)
58
+ at(index)
59
59
  end
60
60
  end
61
61
 
62
+ # Delete the element(s) from the list that match name. If count is specified,
63
+ # only the first-N (if positive) or last-N (if negative) will be removed.
64
+ # Redis: LREM
62
65
  def delete(name, count=0)
63
- redis.lrem(name, count)
66
+ redis.lrem(key, count, name) # weird api
67
+ get
68
+ end
69
+
70
+ # Iterate through each member of the set. Redis::Objects mixes in Enumerable,
71
+ # so you can also use familiar methods like +collect+, +detect+, and so forth.
72
+ def each(&block)
73
+ values.each(&block)
64
74
  end
65
75
 
76
+ # Return a range of values from +start_index+ to +end_index+. Can also use
77
+ # the familiar list[start,end] Ruby syntax. Redis: LRANGE
66
78
  def range(start_index, end_index)
67
79
  redis.lrange(key, start_index, end_index)
68
80
  end
69
-
81
+
82
+ # Return the value at the given index. Can also use familiar list[index] syntax.
83
+ # Redis: LINDEX
70
84
  def at(index)
71
- redis.lrange(key, index, index)
85
+ redis.lindex(key, index)
86
+ end
87
+
88
+ # Return the first element in the list. Redis: LINDEX(0)
89
+ def first
90
+ at(0)
72
91
  end
73
92
 
93
+ # Return the last element in the list. Redis: LINDEX(-1)
74
94
  def last
75
- redis.lrange(key, -1, -1)
95
+ at(-1)
76
96
  end
77
97
 
98
+ # Clear the list entirely. Redis: DEL
78
99
  def clear
79
100
  redis.del(key)
80
101
  end
81
102
 
103
+ # Return the length of the list. Aliased as size. Redis: LLEN
82
104
  def length
83
- redis.length
105
+ redis.llen(key)
84
106
  end
85
107
  alias_method :size, :length
86
-
108
+
109
+ # Returns true if there are no elements in the list. Redis: LLEN == 0
87
110
  def empty?
88
- values.empty?
111
+ length == 0
89
112
  end
90
-
113
+
91
114
  def ==(x)
92
115
  values == x
93
116
  end
117
+
118
+ def to_s
119
+ values.join(', ')
120
+ end
94
121
  end
95
122
  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}].merge(:redis => redis))
27
+ @#{name} ||= Redis::Counter.new(field_key(:#{name}), redis, self.class.counters[:#{name}])
28
28
  end
29
29
  EndMethods
30
30
  end
@@ -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}].merge(:redis => redis))
23
+ @#{name} ||= Redis::List.new(field_key(:#{name}), redis, self.class.lists[:#{name}])
24
24
  end
25
25
  EndMethods
26
26
  end
@@ -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}].merge(:redis => redis))
25
+ @#{name}_lock ||= Redis::Lock.new(field_key(:#{name}_lock), redis, self.class.locks[:#{name}])
26
26
  end
27
27
  EndMethods
28
28
  end
@@ -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
@@ -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}].merge(:redis => redis))
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,74 @@ 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
+ alias_method :include?, :member?
39
+
40
+ # Delete the value from the set. Redis: SREM
41
+ def delete(name)
42
+ redis.srem(key, name)
43
+ get
44
+ end
45
+
46
+ # Wipe the set entirely. Redis: DEL
47
+ def clear
48
+ redis.del(key)
49
+ end
50
+
51
+ # Iterate through each member of the set. Redis::Objects mixes in Enumerable,
52
+ # so you can also use familiar methods like +collect+, +detect+, and so forth.
53
+ def each(&block)
54
+ members.each(&block)
55
+ end
56
+
57
+ # The number of members in the set. Aliased as size. Redis: SCARD
58
+ def length
59
+ redis.scard(key)
60
+ end
61
+ alias_method :size, :length
62
+
63
+ # Returns true if the set has no members. Redis: SCARD == 0
64
+ def empty?
65
+ length == 0
66
+ end
67
+
68
+ def ==(x)
69
+ members == x
70
+ end
71
+
72
+ def to_s
73
+ members.join(', ')
74
+ end
6
75
  end
7
76
  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,110 @@ 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.first.should == 'b'
268
+ @roster.player_stats.last.should == 'c'
269
+ @roster.player_stats << 'd'
270
+ @roster.player_stats.should == ['b','a','c','d']
271
+ @roster.player_stats[1].should == 'a'
272
+ @roster.player_stats[0].should == 'b'
273
+ @roster.player_stats[2].should == 'c'
274
+ @roster.player_stats[3].should == 'd'
275
+ @roster.player_stats.include?('c').should be_true
276
+ @roster.player_stats.include?('no').should be_false
277
+ @roster.player_stats.pop
278
+ @roster.player_stats[0].should == @roster.player_stats.at(0)
279
+ @roster.player_stats[1].should == @roster.player_stats.at(1)
280
+ @roster.player_stats[2].should == @roster.player_stats.at(2)
281
+ @roster.player_stats.should == ['b','a','c']
282
+ @roster.player_stats.get.should == ['b','a','c']
283
+ @roster.player_stats.shift
284
+ @roster.player_stats.should == ['a','c']
285
+ @roster.player_stats.get.should == ['a','c']
286
+ @roster.player_stats << 'e' << 'f' << 'e'
287
+ @roster.player_stats.should == ['a','c','e','f','e']
288
+ @roster.player_stats.get.should == ['a','c','e','f','e']
289
+ @roster.player_stats.delete('e')
290
+ @roster.player_stats.should == ['a','c','f']
291
+ @roster.player_stats.get.should == ['a','c','f']
292
+ @roster.player_stats << 'j'
293
+ @roster.player_stats.should == ['a','c','f','j']
294
+ @roster.player_stats[0..2].should == ['a','c','f']
295
+ @roster.player_stats[1, 3].should == ['c','f','j']
296
+ @roster.player_stats.length.should == 4
297
+ @roster.player_stats.size.should == 4
298
+ @roster.player_stats.should == ['a','c','f','j']
299
+ @roster.player_stats.get.should == ['a','c','f','j']
300
+
301
+ i = -1
302
+ @roster.player_stats.each do |st|
303
+ st.should == @roster.player_stats[i += 1]
304
+ end
305
+ @roster.player_stats.should == ['a','c','f','j']
306
+ @roster.player_stats.get.should == ['a','c','f','j']
307
+
308
+ @roster.player_stats.each_with_index do |st,i|
309
+ st.should == @roster.player_stats[i]
310
+ end
311
+ @roster.player_stats.should == ['a','c','f','j']
312
+ @roster.player_stats.get.should == ['a','c','f','j']
313
+
314
+ coll = @roster.player_stats.collect{|st| st}
315
+ coll.should == ['a','c','f','j']
316
+ @roster.player_stats.should == ['a','c','f','j']
317
+ @roster.player_stats.get.should == ['a','c','f','j']
318
+
319
+ @roster.player_stats << 'a'
320
+ coll = @roster.player_stats.select{|st| st == 'a'}
321
+ coll.should == ['a','a']
322
+ @roster.player_stats.should == ['a','c','f','j','a']
323
+ @roster.player_stats.get.should == ['a','c','f','j','a']
324
+ end
325
+
326
+ it "should handle sets of simple values" do
327
+ @roster.outfielders.should be_empty
328
+ @roster.outfielders << 'a' << 'a' << 'a'
329
+ @roster.outfielders.should == ['a']
330
+ @roster.outfielders.get.should == ['a']
331
+ @roster.outfielders << 'b' << 'b'
332
+ @roster.outfielders.to_s.should == 'a, b'
333
+ @roster.outfielders.should == ['a','b']
334
+ @roster.outfielders.members.should == ['a','b']
335
+ @roster.outfielders.get.should == ['a','b']
336
+ @roster.outfielders << 'c'
337
+ @roster.outfielders.sort.should == ['a','b','c']
338
+ @roster.outfielders.get.sort.should == ['a','b','c']
339
+ @roster.outfielders.delete('c')
340
+ @roster.outfielders.should == ['a','b']
341
+ @roster.outfielders.get.sort.should == ['a','b']
342
+ @roster.outfielders.length.should == 2
343
+ @roster.outfielders.size.should == 2
344
+
345
+ i = 0
346
+ @roster.outfielders.each do |st|
347
+ i += 1
348
+ end
349
+ i.should == @roster.outfielders.length
350
+
351
+ coll = @roster.outfielders.collect{|st| st}
352
+ coll.should == ['a','b']
353
+ @roster.outfielders.should == ['a','b']
354
+ @roster.outfielders.get.should == ['a','b']
355
+
356
+ @roster.outfielders << 'c'
357
+ @roster.outfielders.member?('c').should be_true
358
+ @roster.outfielders.include?('c').should be_true
359
+ @roster.outfielders.member?('no').should be_false
360
+ coll = @roster.outfielders.select{|st| st == 'c'}
361
+ coll.should == ['c']
362
+ @roster.outfielders.sort.should == ['a','b','c']
257
363
  end
258
364
 
259
365
  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.0
4
+ version: 0.1.2
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-24 00:00:00 -08:00
12
+ date: 2009-11-26 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: Redis::Objects is a lightweight library that lets you use Redis primitives as Ruby objects from any class or ORM
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: Lightweight map of Redis types to Ruby objects
71
+ summary: Maps Redis types to Ruby objects
72
72
  test_files: []
73
73