redis-objects 0.7.0 → 0.8.0
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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.rdoc +16 -0
- data/Gemfile +3 -7
- data/LICENSE +202 -0
- data/README.md +36 -23
- data/Rakefile +2 -55
- data/lib/redis/hash_key.rb +1 -1
- data/lib/redis/list.rb +9 -9
- data/lib/redis/objects.rb +23 -25
- data/lib/redis/objects/counters.rb +19 -16
- data/lib/redis/objects/hashes.rb +19 -16
- data/lib/redis/objects/lists.rb +19 -16
- data/lib/redis/objects/locks.rb +19 -16
- data/lib/redis/objects/sets.rb +19 -17
- data/lib/redis/objects/sorted_sets.rb +19 -16
- data/lib/redis/objects/values.rb +25 -26
- data/lib/redis/objects/version.rb +5 -0
- data/lib/redis/sorted_set.rb +11 -5
- data/redis-objects.gemspec +25 -71
- data/spec/redis_objects_instance_spec.rb +88 -46
- data/spec/redis_objects_model_spec.rb +37 -11
- metadata +74 -28
data/lib/redis/hash_key.rb
CHANGED
@@ -118,7 +118,7 @@ class Redis
|
|
118
118
|
|
119
119
|
# Set keys in bulk if they do not exist. Takes a hash of field/values {'field1' => 'val1'}. Redis: HSETNX
|
120
120
|
def fill(pairs={})
|
121
|
-
raise
|
121
|
+
raise ArgumentError, "Arugment to fill must be a hash of key/value pairs" unless pairs.is_a?(::Hash)
|
122
122
|
pairs.each do |field, value|
|
123
123
|
redis.hsetnx(key, field, to_redis(value, options[:marshal_keys][field]))
|
124
124
|
end
|
data/lib/redis/list.rb
CHANGED
@@ -20,15 +20,15 @@ class Redis
|
|
20
20
|
push(value)
|
21
21
|
self # for << 'a' << 'b'
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# Add a member before or after pivot in the list. Redis: LINSERT
|
25
25
|
def insert(where,pivot,value)
|
26
26
|
redis.linsert(key,where,to_redis(pivot),to_redis(value))
|
27
27
|
end
|
28
28
|
|
29
29
|
# Add a member to the end of the list. Redis: RPUSH
|
30
|
-
def push(
|
31
|
-
redis.rpush(key, to_redis(
|
30
|
+
def push(*values)
|
31
|
+
redis.rpush(key, values.map{|v| to_redis(v) })
|
32
32
|
redis.ltrim(key, -options[:maxlength], -1) if options[:maxlength]
|
33
33
|
end
|
34
34
|
|
@@ -50,8 +50,8 @@ class Redis
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Add a member to the start of the list. Redis: LPUSH
|
53
|
-
def unshift(
|
54
|
-
redis.lpush(key, to_redis(
|
53
|
+
def unshift(*values)
|
54
|
+
redis.lpush(key, values.map{|v| to_redis(v) })
|
55
55
|
redis.ltrim(key, 0, options[:maxlength] - 1) if options[:maxlength]
|
56
56
|
end
|
57
57
|
|
@@ -88,7 +88,7 @@ class Redis
|
|
88
88
|
|
89
89
|
# Same functionality as Ruby arrays.
|
90
90
|
def []=(index, value)
|
91
|
-
redis.lset(key, index, value)
|
91
|
+
redis.lset(key, index, to_redis(value))
|
92
92
|
end
|
93
93
|
|
94
94
|
# Delete the element(s) from the list that match name. If count is specified,
|
@@ -132,16 +132,16 @@ class Redis
|
|
132
132
|
redis.llen(key)
|
133
133
|
end
|
134
134
|
alias_method :size, :length
|
135
|
-
|
135
|
+
|
136
136
|
# Returns true if there are no elements in the list. Redis: LLEN == 0
|
137
137
|
def empty?
|
138
138
|
length == 0
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
def ==(x)
|
142
142
|
values == x
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def to_s
|
146
146
|
values.join(', ')
|
147
147
|
end
|
data/lib/redis/objects.rb
CHANGED
@@ -109,19 +109,24 @@ class Redis
|
|
109
109
|
downcase
|
110
110
|
end
|
111
111
|
|
112
|
-
def redis_field_key(name, id=nil) #:nodoc:
|
112
|
+
def redis_field_key(name, id=nil, context=self) #:nodoc:
|
113
113
|
klass = first_ancestor_with(name)
|
114
114
|
# READ THIS: This can never ever ever ever change or upgrades will corrupt all data
|
115
115
|
# I don't think people were using Proc as keys before (that would create a weird key). Should be ok
|
116
|
-
key = klass.redis_objects[name.to_sym][:key]
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
116
|
+
if key = klass.redis_objects[name.to_sym][:key]
|
117
|
+
if key.respond_to?(:call)
|
118
|
+
key = key.call context
|
119
|
+
else
|
120
|
+
context.instance_eval "%(#{key})"
|
121
|
+
end
|
122
|
+
else
|
123
|
+
if id.nil? and !klass.redis_objects[name.to_sym][:global]
|
124
|
+
raise NilObjectId,
|
125
|
+
"[#{klass.redis_objects[name.to_sym]}] Attempt to address redis-object " +
|
126
|
+
":#{name} on class #{klass.name} with nil id (unsaved record?) [object_id=#{object_id}]"
|
127
|
+
end
|
128
|
+
"#{redis_prefix(klass)}:#{id}:#{name}"
|
123
129
|
end
|
124
|
-
key || "#{redis_prefix(klass)}:#{id}:#{name}"
|
125
130
|
end
|
126
131
|
|
127
132
|
def first_ancestor_with(name)
|
@@ -131,27 +136,20 @@ class Redis
|
|
131
136
|
superclass.first_ancestor_with(name)
|
132
137
|
end
|
133
138
|
end
|
139
|
+
|
140
|
+
def redis_id_field(id=nil)
|
141
|
+
@redis_id_field = id || @redis_id_field || :id
|
142
|
+
end
|
134
143
|
end
|
135
144
|
|
136
145
|
# Instance methods that appear in your class when you include Redis::Objects.
|
137
146
|
module InstanceMethods
|
138
|
-
|
147
|
+
# Map up one level to make modular extend/include approach sane
|
148
|
+
def redis() self.class.redis end
|
149
|
+
def redis_objects() self.class.redis_objects end
|
150
|
+
|
139
151
|
def redis_field_key(name) #:nodoc:
|
140
|
-
|
141
|
-
if key = klass.redis_objects[name.to_sym][:key]
|
142
|
-
if key.respond_to?(:call)
|
143
|
-
key.call self
|
144
|
-
else
|
145
|
-
eval "%(#{key})"
|
146
|
-
end
|
147
|
-
else
|
148
|
-
if id.nil? and !klass.redis_objects[name.to_sym][:global]
|
149
|
-
raise NilObjectId,
|
150
|
-
"Attempt to address redis-object :#{name} on class #{klass.name} with nil id (unsaved record?) [object_id=#{object_id}]"
|
151
|
-
end
|
152
|
-
# don't try to refactor into class redis_field_key because fucks up eval context
|
153
|
-
"#{klass.redis_prefix}:#{id}:#{name}"
|
154
|
-
end
|
152
|
+
self.class.redis_field_key(name, send(self.class.redis_id_field), self)
|
155
153
|
end
|
156
154
|
end
|
157
155
|
end
|
@@ -23,24 +23,27 @@ 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
|
-
|
26
|
+
|
27
|
+
mod = Module.new do
|
28
|
+
define_method(name) do
|
29
|
+
instance_variable_get("@#{name}") or
|
30
|
+
instance_variable_set("@#{name}",
|
31
|
+
Redis::Counter.new(
|
32
|
+
redis_field_key(name), redis, redis_objects[name.to_sym]
|
33
|
+
)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
27
38
|
if options[:global]
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def #{name}
|
35
|
-
self.class.#{name}
|
36
|
-
end
|
37
|
-
EndMethods
|
39
|
+
extend mod
|
40
|
+
|
41
|
+
# dispatch to class methods
|
42
|
+
define_method(name) do
|
43
|
+
self.class.public_send(name)
|
44
|
+
end
|
38
45
|
else
|
39
|
-
|
40
|
-
def #{name}
|
41
|
-
@#{name} ||= Redis::Counter.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
|
42
|
-
end
|
43
|
-
EndMethods
|
46
|
+
include mod
|
44
47
|
end
|
45
48
|
end
|
46
49
|
|
data/lib/redis/objects/hashes.rb
CHANGED
@@ -15,24 +15,27 @@ 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
|
-
|
18
|
+
|
19
|
+
mod = Module.new do
|
20
|
+
define_method(name) do
|
21
|
+
instance_variable_get("@#{name}") or
|
22
|
+
instance_variable_set("@#{name}",
|
23
|
+
Redis::HashKey.new(
|
24
|
+
redis_field_key(name), redis, redis_objects[name.to_sym]
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
19
30
|
if options[:global]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def #{name}
|
27
|
-
self.class.#{name}
|
28
|
-
end
|
29
|
-
EndMethods
|
31
|
+
extend mod
|
32
|
+
|
33
|
+
# dispatch to class methods
|
34
|
+
define_method(name) do
|
35
|
+
self.class.public_send(name)
|
36
|
+
end
|
30
37
|
else
|
31
|
-
|
32
|
-
def #{name}
|
33
|
-
@#{name} ||= Redis::HashKey.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
|
34
|
-
end
|
35
|
-
EndMethods
|
38
|
+
include mod
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
data/lib/redis/objects/lists.rb
CHANGED
@@ -15,24 +15,27 @@ 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
|
-
|
18
|
+
|
19
|
+
mod = Module.new do
|
20
|
+
define_method(name) do
|
21
|
+
instance_variable_get("@#{name}") or
|
22
|
+
instance_variable_set("@#{name}",
|
23
|
+
Redis::List.new(
|
24
|
+
redis_field_key(name), redis, redis_objects[name.to_sym]
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
19
30
|
if options[:global]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def #{name}
|
27
|
-
self.class.#{name}
|
28
|
-
end
|
29
|
-
EndMethods
|
31
|
+
extend mod
|
32
|
+
|
33
|
+
# dispatch to class methods
|
34
|
+
define_method(name) do
|
35
|
+
self.class.public_send(name)
|
36
|
+
end
|
30
37
|
else
|
31
|
-
|
32
|
-
def #{name}
|
33
|
-
@#{name} ||= Redis::List.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
|
34
|
-
end
|
35
|
-
EndMethods
|
38
|
+
include mod
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
data/lib/redis/objects/locks.rb
CHANGED
@@ -18,24 +18,27 @@ 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
|
-
|
21
|
+
|
22
|
+
mod = Module.new do
|
23
|
+
define_method(lock_name) do |&block|
|
24
|
+
instance_variable_get("@#{lock_name}") or
|
25
|
+
instance_variable_set("@#{lock_name}",
|
26
|
+
Redis::Lock.new(
|
27
|
+
redis_field_key(lock_name), redis, redis_objects[lock_name.to_sym]
|
28
|
+
)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
22
33
|
if options[:global]
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
def #{lock_name}(&block)
|
30
|
-
self.class.#{lock_name}(block)
|
31
|
-
end
|
32
|
-
EndMethods
|
34
|
+
extend mod
|
35
|
+
|
36
|
+
# dispatch to class methods
|
37
|
+
define_method(lock_name) do |&block|
|
38
|
+
self.class.public_send(lock_name, &block)
|
39
|
+
end
|
33
40
|
else
|
34
|
-
|
35
|
-
def #{lock_name}(&block)
|
36
|
-
@#{lock_name} ||= Redis::Lock.new(redis_field_key(:#{lock_name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{lock_name}])
|
37
|
-
end
|
38
|
-
EndMethods
|
41
|
+
include mod
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
data/lib/redis/objects/sets.rb
CHANGED
@@ -15,26 +15,28 @@ 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
|
-
|
18
|
+
|
19
|
+
mod = Module.new do
|
20
|
+
define_method(name) do
|
21
|
+
instance_variable_get("@#{name}") or
|
22
|
+
instance_variable_set("@#{name}",
|
23
|
+
Redis::Set.new(
|
24
|
+
redis_field_key(name), redis, redis_objects[name.to_sym]
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
19
30
|
if options[:global]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def #{name}
|
27
|
-
self.class.#{name}
|
28
|
-
end
|
29
|
-
EndMethods
|
31
|
+
extend mod
|
32
|
+
|
33
|
+
# dispatch to class methods
|
34
|
+
define_method(name) do
|
35
|
+
self.class.public_send(name)
|
36
|
+
end
|
30
37
|
else
|
31
|
-
|
32
|
-
def #{name}
|
33
|
-
@#{name} ||= Redis::Set.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
|
34
|
-
end
|
35
|
-
EndMethods
|
38
|
+
include mod
|
36
39
|
end
|
37
|
-
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
@@ -15,24 +15,27 @@ 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
|
-
|
18
|
+
|
19
|
+
mod = Module.new do
|
20
|
+
define_method(name) do
|
21
|
+
instance_variable_get("@#{name}") or
|
22
|
+
instance_variable_set("@#{name}",
|
23
|
+
Redis::SortedSet.new(
|
24
|
+
redis_field_key(name), redis, redis_objects[name.to_sym]
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
19
30
|
if options[:global]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def #{name}
|
27
|
-
self.class.#{name}
|
28
|
-
end
|
29
|
-
EndMethods
|
31
|
+
extend mod
|
32
|
+
|
33
|
+
# dispatch to class methods
|
34
|
+
define_method(name) do
|
35
|
+
self.class.public_send(name)
|
36
|
+
end
|
30
37
|
else
|
31
|
-
|
32
|
-
def #{name}
|
33
|
-
@#{name} ||= Redis::SortedSet.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
|
34
|
-
end
|
35
|
-
EndMethods
|
38
|
+
include mod
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
data/lib/redis/objects/values.rb
CHANGED
@@ -15,35 +15,34 @@ 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
|
-
|
18
|
+
|
19
|
+
mod = Module.new do
|
20
|
+
define_method(name) do
|
21
|
+
instance_variable_get("@#{name}") or
|
22
|
+
instance_variable_set("@#{name}",
|
23
|
+
Redis::Value.new(
|
24
|
+
redis_field_key(name), redis, redis_objects[name.to_sym]
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
28
|
+
define_method("#{name}=") do |value|
|
29
|
+
public_send(name).value = value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
19
33
|
if options[:global]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
def #{name}
|
30
|
-
self.class.#{name}
|
31
|
-
end
|
32
|
-
def #{name}=(value)
|
33
|
-
self.class.#{name} = value
|
34
|
-
end
|
35
|
-
EndMethods
|
34
|
+
extend mod
|
35
|
+
|
36
|
+
# dispatch to class methods
|
37
|
+
define_method(name) do
|
38
|
+
self.class.public_send(name)
|
39
|
+
end
|
40
|
+
define_method("#{name}=") do |value|
|
41
|
+
self.class.public_send("#{name}=", value)
|
42
|
+
end
|
36
43
|
else
|
37
|
-
|
38
|
-
def #{name}
|
39
|
-
@#{name} ||= Redis::Value.new(redis_field_key(:#{name}), #{klass_name}.redis, #{klass_name}.redis_objects[:#{name}])
|
40
|
-
end
|
41
|
-
def #{name}=(value)
|
42
|
-
#{name}.value = value
|
43
|
-
end
|
44
|
-
EndMethods
|
44
|
+
include mod
|
45
45
|
end
|
46
|
-
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|