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 +90 -23
- data/lib/redis/counter.rb +2 -3
- data/lib/redis/list.rb +59 -32
- 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 +69 -0
- data/lib/redis/value.rb +2 -2
- data/spec/redis_objects_model_spec.rb +106 -0
- metadata +4 -4
data/README.rdoc
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
= Redis::Objects -
|
|
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
|
|
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,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
|
-
|
|
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
|
+
@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
|
-
|
|
72
|
+
Note counters cannot be assigned to, only incremented/decremented:
|
|
57
73
|
|
|
58
|
-
@team.
|
|
59
|
-
@team.
|
|
60
|
-
@team.
|
|
61
|
-
@team.
|
|
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
|
-
|
|
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
|
-
|
|
70
|
-
puts @counter.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
# 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(
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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}]
|
|
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,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.
|
|
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-
|
|
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
|
|