blendris 0.5 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -0
- data/Manifest +1 -1
- data/README.markdown +124 -12
- data/Rakefile +2 -2
- data/blendris.gemspec +7 -5
- data/lib/blendris/accessor.rb +57 -16
- data/lib/blendris/errors.rb +0 -2
- data/lib/blendris/integer.rb +5 -3
- data/lib/blendris/list.rb +13 -2
- data/lib/blendris/model.rb +18 -35
- data/lib/blendris/node.rb +22 -1
- data/lib/blendris/reference.rb +0 -2
- data/lib/blendris/reference_base.rb +5 -7
- data/lib/blendris/reference_set.rb +15 -3
- data/lib/blendris/set.rb +1 -2
- data/lib/blendris/string.rb +1 -3
- data/spec/integer_spec.rb +15 -0
- data/spec/list_spec.rb +6 -0
- data/spec/model_spec.rb +9 -2
- data/spec/ref_spec.rb +9 -0
- data/spec/spec_helper.rb +11 -3
- metadata +35 -8
- metadata.gz.sig +1 -0
- data/tasks/rspec.rake +0 -21
data.tar.gz.sig
ADDED
data/Manifest
CHANGED
@@ -21,6 +21,7 @@ lib/blendris/utils.rb
|
|
21
21
|
script/console
|
22
22
|
script/destroy
|
23
23
|
script/generate
|
24
|
+
spec/integer_spec.rb
|
24
25
|
spec/list_spec.rb
|
25
26
|
spec/model_spec.rb
|
26
27
|
spec/redis-tools_spec.rb
|
@@ -29,4 +30,3 @@ spec/set_spec.rb
|
|
29
30
|
spec/spec.opts
|
30
31
|
spec/spec_helper.rb
|
31
32
|
spec/string_spec.rb
|
32
|
-
tasks/rspec.rake
|
data/README.markdown
CHANGED
@@ -6,7 +6,8 @@ http://github.com/alexmchale/blendris
|
|
6
6
|
|
7
7
|
# DESCRIPTION #
|
8
8
|
|
9
|
-
Blendris is a Ruby interface to a Redis database.
|
9
|
+
Blendris is a Ruby interface to a Redis database. It performs no caching,
|
10
|
+
causing all reads and writes to interact directly with Redis.
|
10
11
|
|
11
12
|
|
12
13
|
|
@@ -58,33 +59,74 @@ Let's say we want to maintain a list of employers and employees.
|
|
58
59
|
ref :employer, :class => "Employer", :reverse => :employees
|
59
60
|
end
|
60
61
|
|
62
|
+
And now some examples of using them:
|
63
|
+
|
64
|
+
>> captain = Employee.create("Captain Amazing")
|
65
|
+
=> #<Employee:0x45d18084 @key="employee:Captain_Amazing">
|
66
|
+
|
67
|
+
>> captain.address = "123 Fake Street"
|
68
|
+
=> "123 Fake Street"
|
69
|
+
|
70
|
+
>> guild = Employer.create("The Really Fantastic Guild of Heroes")
|
71
|
+
=> #<Employer:0x476e46f5 @key="employer:The_Really_Fantastic_Guild_of_Heroes">
|
72
|
+
|
73
|
+
>> guild.employees << captain
|
74
|
+
=> #<Blendris::RedisReferenceSet:0x500150a0 @key="employer:The_Really_Fantastic_Guild_of_Heroes:employees", ...>
|
75
|
+
|
76
|
+
>> guild.employees.first.address
|
77
|
+
=> "123 Fake Street"
|
78
|
+
|
79
|
+
>> guild.employees.count
|
80
|
+
=> 1
|
81
|
+
|
82
|
+
>> guild.employees.first.employer.employees.first.name
|
83
|
+
=> "Captain Amazing"
|
84
|
+
|
61
85
|
### key ###
|
62
86
|
|
63
|
-
Key sets the base key for this object.
|
64
|
-
"37 Signals" it would create a key "employer:37_Signals" and set its value
|
65
|
-
to "Employer". In the key, strings are interpreted as literals and
|
66
|
-
symbols are interpreted as pointers to that data field.
|
87
|
+
Key sets the base key for this object.
|
67
88
|
|
68
|
-
*
|
69
|
-
|
70
|
-
*
|
71
|
-
|
89
|
+
* Any strings in the key will be used as literal strings.
|
90
|
+
* Any symbols in the key will be set to the value of that field in this object.
|
91
|
+
* In the case of the employer "37 Signals" it would create a key
|
92
|
+
"employer:37_Signals" and set its value to "Employer".
|
93
|
+
* Note that spaces are converted to underscores, as spaces are not allowed in
|
94
|
+
Redis keys. This could cause problems in some data sets.
|
95
|
+
* Also note that the value assigned to the base key is the class name of the
|
96
|
+
model being used.
|
72
97
|
* Only strings and integers should be used as key values.
|
73
98
|
|
99
|
+
Examples of keys in use:
|
100
|
+
|
101
|
+
>> employer = Employer.create("37 Signals")
|
102
|
+
=> #<Employer:0x169da74 @key="employer:37_Signals">
|
103
|
+
|
104
|
+
>> employer.key
|
105
|
+
=> "employer:37_Signals"
|
106
|
+
|
107
|
+
>> employer.name
|
108
|
+
=> "37 Signals"
|
109
|
+
|
110
|
+
>> employer[:name]
|
111
|
+
=> #<Blendris::RedisString:0x20dbd794 @key="employer:37_Signals:name", ...>
|
112
|
+
|
113
|
+
>> employer[:name].key
|
114
|
+
=> "employer:37_Signals:name"
|
115
|
+
|
74
116
|
### string ###
|
75
117
|
|
76
118
|
String creates a string key named for the first parameter given to it.
|
77
119
|
This means that it would generate a key "employer:37_Signals:name" with
|
78
120
|
a value of "37 Signals".
|
79
121
|
|
80
|
-
### refs ###
|
122
|
+
### ref and refs ###
|
81
123
|
|
82
|
-
Refs
|
124
|
+
Refs maintain references to other objects.
|
83
125
|
|
84
126
|
* *:class* will limit objects in this reference set to the given class.
|
85
127
|
If a string is specified as a class, it will be constantized before
|
86
128
|
comparing.
|
87
|
-
*
|
129
|
+
* *:reverse* will cause the given field to be updated on the object when
|
88
130
|
it is added to or removed from this set.
|
89
131
|
|
90
132
|
### new vs create ###
|
@@ -96,7 +138,77 @@ the list of symbols in your *key* field.
|
|
96
138
|
Calling the *new* method will instantiate an existing object using the
|
97
139
|
given *key* as the base key.
|
98
140
|
|
141
|
+
Calling *create* on an object key that already exists is perfectly acceptable
|
142
|
+
and only results in new Ruby objects being instantiated. They will all read
|
143
|
+
and write to the same Redis data. Calling *new* however must be done on a
|
144
|
+
Redis key that already exists and is set to the name of the requested model.
|
145
|
+
|
146
|
+
>> Employer.create("Giant Faceless Corporation")
|
147
|
+
=> #<Employer:0x45a84b38 @key="employer:Giant_Faceless_Corporation">
|
148
|
+
|
149
|
+
>> Employer.create("Giant Faceless Corporation")
|
150
|
+
=> #<Employer:0x12b8501d @key="employer:Giant_Faceless_Corporation">
|
151
|
+
|
152
|
+
>> Employer.create("Giant Faceless Corporation")
|
153
|
+
=> #<Employer:0x742136c6 @key="employer:Giant_Faceless_Corporation">
|
154
|
+
|
155
|
+
>> Employer.new("Anything")
|
156
|
+
TypeError: Anything does not exist, not a Employer - you may want create instead of new
|
157
|
+
from .../blendris/lib/blendris/model.rb:25:in `initialize'
|
158
|
+
from (irb):32:in `new'
|
159
|
+
from (irb):32
|
160
|
+
|
161
|
+
>> Employer.new("employer:Giant_Faceless_Corporation")
|
162
|
+
=> #<Employer:0x73cb4cae @key="employer:Giant_Faceless_Corporation">
|
163
|
+
|
164
|
+
>> Employee.create("Invisible Woman")
|
165
|
+
=> #<Employee:0x5f27a49c @key="employee:Invisible_Woman">
|
166
|
+
|
167
|
+
>> Employer.new("employee:Invisible_Woman")
|
168
|
+
TypeError: employee:Invisible_Woman is a Employee, not a Employer
|
169
|
+
from /Users/amchale/Dropbox/Projects/blendris/lib/blendris/model.rb:26:in `initialize'
|
170
|
+
from (irb):36:in `new'
|
171
|
+
from (irb):36
|
172
|
+
|
173
|
+
### on_change ###
|
174
|
+
|
175
|
+
This keyword allows you to execute a block when one or more fields on the
|
176
|
+
object change. The block is executed within the context of the object.
|
177
|
+
|
178
|
+
class Dog < Blendris::Model
|
179
|
+
key "dog", :name
|
180
|
+
|
181
|
+
string :name
|
182
|
+
string :color
|
183
|
+
integer :attention
|
184
|
+
integer :food
|
185
|
+
|
186
|
+
on_change do
|
187
|
+
puts "Bark, bark!"
|
188
|
+
end
|
189
|
+
|
190
|
+
on_change :attention, :food do
|
191
|
+
puts "Woof, woof!"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
>> d = Dog.create("Spot")
|
196
|
+
Bark, bark!
|
197
|
+
=> #<Dog:0x000001011739e8 @key="dog:Spot">
|
198
|
+
|
199
|
+
>> d.attention = 0
|
200
|
+
Bark, bark!
|
201
|
+
Woof, woof!
|
202
|
+
=> 0
|
203
|
+
|
204
|
+
>> d.color = "brown"
|
205
|
+
Bark, bark!
|
206
|
+
=> "brown"
|
99
207
|
|
208
|
+
>> d[:attention].increment
|
209
|
+
Bark, bark!
|
210
|
+
Woof, woof!
|
211
|
+
=> 1
|
100
212
|
|
101
213
|
# LICENSE #
|
102
214
|
|
data/Rakefile
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
require "rubygems"
|
2
|
+
require "rubygems/commands/push_command"
|
2
3
|
|
3
4
|
gem "echoe", ">= 4.1"
|
4
5
|
gem "redis", ">= 0.1.2"
|
5
6
|
|
6
7
|
require "echoe"
|
7
|
-
|
8
8
|
require "redis"
|
9
9
|
require "fileutils"
|
10
10
|
require "./lib/blendris"
|
11
11
|
|
12
|
-
Echoe.new("blendris", "0.
|
12
|
+
Echoe.new("blendris", "0.6") do |p|
|
13
13
|
|
14
14
|
p.description = "A redis library for Ruby"
|
15
15
|
p.url = "http://github.com/alexmchale/blendris"
|
data/blendris.gemspec
CHANGED
@@ -2,20 +2,22 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{blendris}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.6"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Alex McHale"]
|
9
|
-
s.
|
9
|
+
s.cert_chain = ["/Users/alexmchale/Dropbox/Security/gem-public_cert.pem"]
|
10
|
+
s.date = %q{2010-02-27}
|
10
11
|
s.description = %q{A redis library for Ruby}
|
11
12
|
s.email = %q{alexmchale@gmail.com}
|
12
|
-
s.extra_rdoc_files = ["README.markdown", "lib/blendris.rb", "lib/blendris/accessor.rb", "lib/blendris/errors.rb", "lib/blendris/integer.rb", "lib/blendris/list.rb", "lib/blendris/model.rb", "lib/blendris/node.rb", "lib/blendris/reference.rb", "lib/blendris/reference_base.rb", "lib/blendris/reference_set.rb", "lib/blendris/set.rb", "lib/blendris/string.rb", "lib/blendris/types.rb", "lib/blendris/utils.rb"
|
13
|
-
s.files = ["History.txt", "Manifest", "PostInstall.txt", "README.markdown", "Rakefile", "autotest/discover.rb", "lib/blendris.rb", "lib/blendris/accessor.rb", "lib/blendris/errors.rb", "lib/blendris/integer.rb", "lib/blendris/list.rb", "lib/blendris/model.rb", "lib/blendris/node.rb", "lib/blendris/reference.rb", "lib/blendris/reference_base.rb", "lib/blendris/reference_set.rb", "lib/blendris/set.rb", "lib/blendris/string.rb", "lib/blendris/types.rb", "lib/blendris/utils.rb", "script/console", "script/destroy", "script/generate", "spec/list_spec.rb", "spec/model_spec.rb", "spec/redis-tools_spec.rb", "spec/ref_spec.rb", "spec/set_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/string_spec.rb", "
|
13
|
+
s.extra_rdoc_files = ["README.markdown", "lib/blendris.rb", "lib/blendris/accessor.rb", "lib/blendris/errors.rb", "lib/blendris/integer.rb", "lib/blendris/list.rb", "lib/blendris/model.rb", "lib/blendris/node.rb", "lib/blendris/reference.rb", "lib/blendris/reference_base.rb", "lib/blendris/reference_set.rb", "lib/blendris/set.rb", "lib/blendris/string.rb", "lib/blendris/types.rb", "lib/blendris/utils.rb"]
|
14
|
+
s.files = ["History.txt", "Manifest", "PostInstall.txt", "README.markdown", "Rakefile", "autotest/discover.rb", "lib/blendris.rb", "lib/blendris/accessor.rb", "lib/blendris/errors.rb", "lib/blendris/integer.rb", "lib/blendris/list.rb", "lib/blendris/model.rb", "lib/blendris/node.rb", "lib/blendris/reference.rb", "lib/blendris/reference_base.rb", "lib/blendris/reference_set.rb", "lib/blendris/set.rb", "lib/blendris/string.rb", "lib/blendris/types.rb", "lib/blendris/utils.rb", "script/console", "script/destroy", "script/generate", "spec/integer_spec.rb", "spec/list_spec.rb", "spec/model_spec.rb", "spec/redis-tools_spec.rb", "spec/ref_spec.rb", "spec/set_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/string_spec.rb", "blendris.gemspec"]
|
14
15
|
s.homepage = %q{http://github.com/alexmchale/blendris}
|
15
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Blendris", "--main", "README.markdown"]
|
16
17
|
s.require_paths = ["lib"]
|
17
18
|
s.rubyforge_project = %q{blendris}
|
18
|
-
s.rubygems_version = %q{1.3.
|
19
|
+
s.rubygems_version = %q{1.3.6}
|
20
|
+
s.signing_key = %q{/Users/alexmchale/Dropbox/Security/gem-private_key.pem}
|
19
21
|
s.summary = %q{A redis library for Ruby}
|
20
22
|
|
21
23
|
if s.respond_to? :specification_version then
|
data/lib/blendris/accessor.rb
CHANGED
@@ -1,5 +1,47 @@
|
|
1
1
|
module Blendris
|
2
2
|
|
3
|
+
class << self
|
4
|
+
|
5
|
+
attr_accessor :host, :port, :database
|
6
|
+
|
7
|
+
# Specify the host to connect to for the Redis connection.
|
8
|
+
def host=(host)
|
9
|
+
@host = host || "localhost"
|
10
|
+
$_redis_connection = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
# Specify the port to connect to for the Redis connection.
|
14
|
+
def port=(port)
|
15
|
+
@port = port.to_i
|
16
|
+
@port = 6379 unless (1 .. 65535).include? @port
|
17
|
+
$_redis_connection = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
# Specify the database number to use in the Redis database.
|
21
|
+
def database=(index)
|
22
|
+
@database = index.to_i
|
23
|
+
$_redis_connection = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieve the connection to the current Redis database.
|
27
|
+
def redis
|
28
|
+
parms =
|
29
|
+
{
|
30
|
+
:host => @host,
|
31
|
+
:port => @port,
|
32
|
+
:db => @database
|
33
|
+
}
|
34
|
+
|
35
|
+
$_redis_connection ||= Redis.new(parms)
|
36
|
+
end
|
37
|
+
|
38
|
+
# This will delete all keys in the current database. Dangerous!
|
39
|
+
def flushdb
|
40
|
+
redis.flushdb
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
3
45
|
# This module serves as a gateway to the Redis library. Any object
|
4
46
|
# that needs to access Redis directly should include it.
|
5
47
|
|
@@ -8,11 +50,11 @@ module Blendris
|
|
8
50
|
include Utils
|
9
51
|
|
10
52
|
def redis
|
11
|
-
|
53
|
+
Blendris.redis
|
12
54
|
end
|
13
55
|
|
14
56
|
def self.redis
|
15
|
-
|
57
|
+
Blendris.redis
|
16
58
|
end
|
17
59
|
|
18
60
|
# Generate a key for the given model class with the given values list.
|
@@ -28,10 +70,15 @@ module Blendris
|
|
28
70
|
when Symbol
|
29
71
|
value = values[value_index]
|
30
72
|
value_index += 1
|
31
|
-
|
32
73
|
raise ArgumentError.new("#{self.name} created without #{symbol}") unless value
|
33
74
|
|
34
|
-
klass.
|
75
|
+
options = klass.redis_symbols[symbol.to_s]
|
76
|
+
raise ArgumentError.new("#{self.name} is missing its #{symbol}") unless options
|
77
|
+
|
78
|
+
subklass = options[:type]
|
79
|
+
raise ArgumentError.new("#{symbol} (#{subklass.name}) cannot be used in the key") unless subklass.respond_to? :cast_to_redis
|
80
|
+
|
81
|
+
subklass.cast_to_redis value, options
|
35
82
|
|
36
83
|
else
|
37
84
|
raise TypeError.new("only strings and symbols allowed in key definition for #{klass.name} (#{symbol.class.name})")
|
@@ -42,16 +89,6 @@ module Blendris
|
|
42
89
|
end.compact.join(":")
|
43
90
|
end
|
44
91
|
|
45
|
-
# Change which database we're accessing in Redis.
|
46
|
-
def self.database=(index)
|
47
|
-
$_redis_connection = Redis.new(:db => index.to_i)
|
48
|
-
end
|
49
|
-
|
50
|
-
# This will delete all keys in the current database. Dangerous!
|
51
|
-
def self.flushdb
|
52
|
-
redis.flushdb
|
53
|
-
end
|
54
|
-
|
55
92
|
# Build a new temporary set with the given contents, yielding it to
|
56
93
|
# the passed block. After the block exits, destroy the temporary set.
|
57
94
|
def in_temporary_set(*contents)
|
@@ -59,8 +96,12 @@ module Blendris
|
|
59
96
|
|
60
97
|
temporary_set = RedisSet.new("blendris:temporary:set:#{index}")
|
61
98
|
temporary_set << contents
|
62
|
-
|
63
|
-
|
99
|
+
|
100
|
+
begin
|
101
|
+
yield temporary_set
|
102
|
+
ensure
|
103
|
+
temporary_set.clear
|
104
|
+
end
|
64
105
|
|
65
106
|
self
|
66
107
|
end
|
data/lib/blendris/errors.rb
CHANGED
data/lib/blendris/integer.rb
CHANGED
@@ -3,9 +3,7 @@ module Blendris
|
|
3
3
|
# RedisInteger is a string-value in Redis wrapped up to make
|
4
4
|
# sure that it is used as an integer.
|
5
5
|
|
6
|
-
class RedisInteger
|
7
|
-
|
8
|
-
include RedisNode
|
6
|
+
class RedisInteger < RedisNode
|
9
7
|
|
10
8
|
def self.cast_to_redis(value, options = {})
|
11
9
|
raise TypeError.new("#{value.class.name} is not an integer") unless value.kind_of? Fixnum
|
@@ -19,10 +17,14 @@ module Blendris
|
|
19
17
|
|
20
18
|
def increment
|
21
19
|
redis.incr key
|
20
|
+
ensure
|
21
|
+
notify_changed
|
22
22
|
end
|
23
23
|
|
24
24
|
def decrement
|
25
25
|
redis.decr key
|
26
|
+
ensure
|
27
|
+
notify_changed
|
26
28
|
end
|
27
29
|
|
28
30
|
end
|
data/lib/blendris/list.rb
CHANGED
@@ -2,9 +2,8 @@ module Blendris
|
|
2
2
|
|
3
3
|
# RedisList is a wrapper for the Redis LIST data type.
|
4
4
|
|
5
|
-
class RedisList
|
5
|
+
class RedisList < RedisNode
|
6
6
|
|
7
|
-
include RedisNode
|
8
7
|
include Enumerable
|
9
8
|
|
10
9
|
def initialize(key, options = {})
|
@@ -13,6 +12,18 @@ module Blendris
|
|
13
12
|
@on_change = options[:on_change]
|
14
13
|
end
|
15
14
|
|
15
|
+
def set(*values)
|
16
|
+
# Remove all of the old values.
|
17
|
+
self.clear
|
18
|
+
|
19
|
+
# Add all of the new values.
|
20
|
+
self << values
|
21
|
+
|
22
|
+
self
|
23
|
+
ensure
|
24
|
+
notify_changed
|
25
|
+
end
|
26
|
+
|
16
27
|
def each
|
17
28
|
redis.lrange(key, 0, -1).each do |value|
|
18
29
|
yield value
|
data/lib/blendris/model.rb
CHANGED
@@ -40,34 +40,14 @@ module Blendris
|
|
40
40
|
Digest::SHA1.hexdigest key
|
41
41
|
end
|
42
42
|
|
43
|
-
# TODO: Create the methods in the initialize method instead of depending
|
44
|
-
# on method_missing to dispatch to the correct methods. This will make
|
45
|
-
# these objects better for mocking and stubbing.
|
46
|
-
def method_missing(method_sym, *arguments)
|
47
|
-
(name, setter) = method_sym.to_s.scan(/(.*[^=])(=)?/).first
|
48
|
-
|
49
|
-
if node = redis_symbol(name)
|
50
|
-
if setter
|
51
|
-
if self.class.local_parameters.find {|p| p.kind_of?(Symbol) && p.to_s == name}
|
52
|
-
raise BlendrisCannotSetKeyValue.new(name)
|
53
|
-
end
|
54
|
-
|
55
|
-
return node.set(*arguments)
|
56
|
-
else
|
57
|
-
return node.get
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
super
|
62
|
-
end
|
63
|
-
|
64
43
|
# Look up the given symbol by its name. The list of symbols are defined
|
65
44
|
# when the model is declared.
|
66
|
-
|
67
|
-
|
45
|
+
def [](name)
|
46
|
+
name = name.to_s
|
47
|
+
|
68
48
|
subkey = self.subkey(name)
|
69
49
|
|
70
|
-
options = self.class.redis_symbols[name
|
50
|
+
options = self.class.redis_symbols[name]
|
71
51
|
|
72
52
|
return unless options
|
73
53
|
|
@@ -76,7 +56,6 @@ module Blendris
|
|
76
56
|
|
77
57
|
options[:type].new subkey, options
|
78
58
|
end
|
79
|
-
alias :[] :redis_symbol
|
80
59
|
|
81
60
|
# Calculate the key to address the given child node.
|
82
61
|
def subkey(child)
|
@@ -136,7 +115,7 @@ module Blendris
|
|
136
115
|
obj = new(key, :verify => false)
|
137
116
|
|
138
117
|
parameters.each_with_index do |parm, i|
|
139
|
-
obj
|
118
|
+
obj[parm].set args[i]
|
140
119
|
end
|
141
120
|
|
142
121
|
obj
|
@@ -156,7 +135,7 @@ module Blendris
|
|
156
135
|
end
|
157
136
|
|
158
137
|
def index_key
|
159
|
-
"index:model:#{self.name}"
|
138
|
+
"blendris:index:model:#{self.name}"
|
160
139
|
end
|
161
140
|
|
162
141
|
# Defines a new data type for Blendris:Model construction.
|
@@ -168,6 +147,18 @@ module Blendris
|
|
168
147
|
|
169
148
|
options[:type] = klass
|
170
149
|
redis_symbols[varname] = options
|
150
|
+
|
151
|
+
# Declare the getter for this field.
|
152
|
+
define_method(varname) do
|
153
|
+
self[varname].get
|
154
|
+
end
|
155
|
+
|
156
|
+
# Declare the setter for this field, if it is not a key field.
|
157
|
+
unless local_parameters.find {|p| p.to_s == varname}
|
158
|
+
define_method("#{varname}=") do |value|
|
159
|
+
self[varname].set value
|
160
|
+
end
|
161
|
+
end
|
171
162
|
end
|
172
163
|
end
|
173
164
|
end
|
@@ -182,14 +173,6 @@ module Blendris
|
|
182
173
|
@local_parameters ||= []
|
183
174
|
end
|
184
175
|
|
185
|
-
# Take a value and attempt to make it fit the given field.
|
186
|
-
def cast_value(symbol, value)
|
187
|
-
options = redis_symbols[symbol.to_s]
|
188
|
-
raise ArgumentError.new("#{self.name} is missing its #{symbol}") unless options
|
189
|
-
|
190
|
-
options[:type].cast_to_redis value, options
|
191
|
-
end
|
192
|
-
|
193
176
|
# Define a block to call when one of the given symbol values changes.
|
194
177
|
def on_change(*symbols, &block)
|
195
178
|
symbols.flatten!
|
data/lib/blendris/node.rb
CHANGED
@@ -2,12 +2,19 @@ module Blendris
|
|
2
2
|
|
3
3
|
# RedisNode is used to compose all Redis value wrapper classes.
|
4
4
|
|
5
|
-
|
5
|
+
class RedisNode
|
6
6
|
|
7
7
|
include RedisAccessor
|
8
8
|
|
9
9
|
attr_reader :key
|
10
10
|
|
11
|
+
# Initialize a new node, which represents a basic Redis data object.
|
12
|
+
#
|
13
|
+
# === Parameters ===
|
14
|
+
#
|
15
|
+
# * :on_change - Pass a block to be run within the context of this object
|
16
|
+
# when its value is changed.
|
17
|
+
# * :default - Use the given value as a default value.
|
11
18
|
def initialize(key, options = {})
|
12
19
|
@key = sanitize_key(key)
|
13
20
|
@default = options[:default]
|
@@ -19,6 +26,12 @@ module Blendris
|
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
29
|
+
# Set this object's value to be the given value.
|
30
|
+
#
|
31
|
+
# * The method cast_to_redis should be overridden by classes that
|
32
|
+
# include this module, as it is used to determine how to convert
|
33
|
+
# the given value to a redis string.
|
34
|
+
# * The on_change block is always called after this method.
|
22
35
|
def set(value)
|
23
36
|
if value
|
24
37
|
redis.set key, self.class.cast_to_redis(value, @options)
|
@@ -29,14 +42,22 @@ module Blendris
|
|
29
42
|
notify_changed
|
30
43
|
end
|
31
44
|
|
45
|
+
# Retrieve the value of this object and cast it.
|
46
|
+
#
|
47
|
+
# * The method cast_from_redis should be overridden by classes that
|
48
|
+
# include this module. It is used to convert the redis string
|
49
|
+
# to this specific object type.
|
32
50
|
def get
|
33
51
|
self.class.cast_from_redis redis.get(self.key), @options
|
34
52
|
end
|
35
53
|
|
54
|
+
# Rename this key to the given new key name.
|
36
55
|
def rename(newkey)
|
37
56
|
redis.rename @key, sanitize_key(newkey)
|
38
57
|
|
39
58
|
@key = newkey
|
59
|
+
ensure
|
60
|
+
notify_changed
|
40
61
|
end
|
41
62
|
|
42
63
|
def clear
|
data/lib/blendris/reference.rb
CHANGED
@@ -3,17 +3,15 @@ module Blendris
|
|
3
3
|
# RedisReferenceBase holds the methods that are common to
|
4
4
|
# RedisReference objects and RedisReferenceSet objects.
|
5
5
|
|
6
|
-
class RedisReferenceBase
|
6
|
+
class RedisReferenceBase < RedisNode
|
7
7
|
|
8
|
-
include RedisNode
|
9
8
|
extend RedisAccessor
|
10
9
|
|
11
10
|
def initialize(key, options = {})
|
11
|
+
super key, options
|
12
|
+
|
12
13
|
@model = options[:model]
|
13
|
-
@key = sanitize_key(key)
|
14
14
|
@reverse = options[:reverse]
|
15
|
-
@options = options
|
16
|
-
@on_change = options[:on_change]
|
17
15
|
|
18
16
|
@klass = options[:class] || Model
|
19
17
|
@klass = constantize(camelize @klass) if @klass.kind_of? String
|
@@ -25,14 +23,14 @@ module Blendris
|
|
25
23
|
|
26
24
|
def apply_reverse_add(value)
|
27
25
|
if @reverse && value
|
28
|
-
reverse = value
|
26
|
+
reverse = value[@reverse]
|
29
27
|
reverse.assign_ref(@model) if !reverse.references @model
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
31
|
def apply_reverse_delete(value)
|
34
32
|
if @reverse && value
|
35
|
-
reverse = value
|
33
|
+
reverse = value[@reverse]
|
36
34
|
reverse.remove_ref(@model) if reverse.references @model
|
37
35
|
end
|
38
36
|
end
|
@@ -5,7 +5,6 @@ module Blendris
|
|
5
5
|
|
6
6
|
class RedisReferenceSet < RedisReferenceBase
|
7
7
|
|
8
|
-
include RedisNode
|
9
8
|
include Enumerable
|
10
9
|
|
11
10
|
def refs
|
@@ -13,8 +12,21 @@ module Blendris
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def set(*objs)
|
16
|
-
|
17
|
-
|
15
|
+
objs.flatten!
|
16
|
+
objs.compact!
|
17
|
+
|
18
|
+
# Delete reference keys that were removed.
|
19
|
+
self.each do |obj|
|
20
|
+
unless objs.include? obj
|
21
|
+
apply_reverse_delete obj
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Clear the current set.
|
26
|
+
self.refs.clear
|
27
|
+
|
28
|
+
# Add the new objects to the set.
|
29
|
+
self << objs
|
18
30
|
|
19
31
|
self
|
20
32
|
ensure
|
data/lib/blendris/set.rb
CHANGED
data/lib/blendris/string.rb
CHANGED
@@ -2,9 +2,7 @@ module Blendris
|
|
2
2
|
|
3
3
|
# RedisString is a wrapper to the Redis string data type.
|
4
4
|
|
5
|
-
class RedisString
|
6
|
-
|
7
|
-
include RedisNode
|
5
|
+
class RedisString < RedisNode
|
8
6
|
|
9
7
|
def self.cast_to_redis(value, options = {})
|
10
8
|
raise TypeError.new("#{value.class.name} is not a string") unless value.kind_of? String
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe "redis integers" do
|
4
|
+
|
5
|
+
it "should always be an integer" do
|
6
|
+
@onion.calories.should == 0
|
7
|
+
@onion.calories = 450
|
8
|
+
@onion.calories.should == 450
|
9
|
+
@onion[:calories].increment.should == 451
|
10
|
+
@onion.calories.should == 451
|
11
|
+
@onion[:calories].decrement.should == 450
|
12
|
+
@onion.calories.should == 450
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/spec/list_spec.rb
CHANGED
@@ -14,4 +14,10 @@ describe "redis lists" do
|
|
14
14
|
@onion.sales.to_a.should == %w( to-tom to-tom )
|
15
15
|
end
|
16
16
|
|
17
|
+
it "should be able to be set to a new list" do
|
18
|
+
@onion.sales = %w( one two three )
|
19
|
+
@onion.sales.count.should == 3
|
20
|
+
@onion.sales.to_a.should == %w( one two three )
|
21
|
+
end
|
22
|
+
|
17
23
|
end
|
data/spec/model_spec.rb
CHANGED
@@ -22,8 +22,11 @@ describe Model do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should not allow its key values to be changed" do
|
25
|
-
|
26
|
-
|
25
|
+
@onion.should respond_to :name
|
26
|
+
@onion.should_not respond_to :name=
|
27
|
+
|
28
|
+
@onion.should respond_to :description
|
29
|
+
@onion.should respond_to :description=
|
27
30
|
end
|
28
31
|
|
29
32
|
it "should have a valid reference set" do
|
@@ -225,4 +228,8 @@ describe Model do
|
|
225
228
|
lambda { o.refs << o }.should raise_exception TestEx
|
226
229
|
end
|
227
230
|
|
231
|
+
it "should be ok when you have sets and lists in the key" do
|
232
|
+
lambda { WeirdKeyModel.create([ "ok" ], [ "weird" ]) }.should raise_exception(ArgumentError)
|
233
|
+
end
|
234
|
+
|
228
235
|
end
|
data/spec/ref_spec.rb
CHANGED
@@ -35,6 +35,15 @@ describe "references" do
|
|
35
35
|
@fruit.foods.count.should == 0
|
36
36
|
@onion.category.should == @vegetable
|
37
37
|
|
38
|
+
@vegetable.foods = [ @apple, @lemon, @lemon ]
|
39
|
+
@vegetable.foods << @apple
|
40
|
+
@vegetable.foods.count.should == 2
|
41
|
+
@vegetable.foods.should be_include @apple
|
42
|
+
@vegetable.foods.should be_include @lemon
|
43
|
+
@apple.category.should == @vegetable
|
44
|
+
@lemon.category.should == @vegetable
|
45
|
+
@onion.category.should == nil
|
46
|
+
|
38
47
|
end
|
39
48
|
|
40
49
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -75,6 +75,13 @@ module TestFixtures
|
|
75
75
|
on_change { raise TestEx.new }
|
76
76
|
end
|
77
77
|
|
78
|
+
class WeirdKeyModel < Blendris::Model
|
79
|
+
key "setkey", :myset, "listkey", :mylist
|
80
|
+
|
81
|
+
set :myset
|
82
|
+
list :mylist
|
83
|
+
end
|
84
|
+
|
78
85
|
class TestEx < Exception; end
|
79
86
|
|
80
87
|
end
|
@@ -83,8 +90,8 @@ Spec::Runner.configure do |config|
|
|
83
90
|
include TestFixtures
|
84
91
|
|
85
92
|
config.before(:each) do
|
86
|
-
|
87
|
-
|
93
|
+
Blendris.database = 11
|
94
|
+
Blendris.flushdb
|
88
95
|
|
89
96
|
@vegetable = Category.create("vegetable")
|
90
97
|
@onion = Food.create("onion")
|
@@ -99,7 +106,8 @@ Spec::Runner.configure do |config|
|
|
99
106
|
end
|
100
107
|
|
101
108
|
config.after(:each) do
|
102
|
-
|
109
|
+
Blendris.database = 11
|
110
|
+
Blendris.flushdb
|
103
111
|
end
|
104
112
|
end
|
105
113
|
|
metadata
CHANGED
@@ -1,15 +1,40 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blendris
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 6
|
8
|
+
version: "0.6"
|
5
9
|
platform: ruby
|
6
10
|
authors:
|
7
11
|
- Alex McHale
|
8
12
|
autorequire:
|
9
13
|
bindir: bin
|
10
|
-
cert_chain:
|
14
|
+
cert_chain:
|
15
|
+
- |
|
16
|
+
-----BEGIN CERTIFICATE-----
|
17
|
+
MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDAphbGV4
|
18
|
+
bWNoYWxlMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
|
19
|
+
b20wHhcNMTAwMjExMjEyNTU4WhcNMTEwMjExMjEyNTU4WjBBMRMwEQYDVQQDDAph
|
20
|
+
bGV4bWNoYWxlMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
|
21
|
+
FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9mTbsd+4JqyuW
|
22
|
+
z/J6OxXyyzb89ydr/wKmJZMyQmD7w/Qf3V8uGW9+NlYbRMJZYqY08QhTbSX3IW6c
|
23
|
+
6Hj4Xo0wqR0Fd6c0Vxdt9m5LZDEo2H+2jisgDBYFUN1itg+FGZtGczISlmG34tWN
|
24
|
+
efWA+DgtzKD9UG13AtzxoxfqeY03v0+/1/SCtpvbZrungWND8sg9sHSxsME0xB9d
|
25
|
+
u6BkunOrdy7iqd105MuPHL35SLhr57GKU/hjR2+FKAauT4eu7CeQXEWCBPXizknN
|
26
|
+
5w/HNs311sBJmzaZwDiX98e+/X10tMxJqWo4t4Us7Ke8b/0uYbuwWoaoKWjM3UYX
|
27
|
+
ppWhyNNFAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
|
28
|
+
BBQK0Aj0bDKnLJrVNjdgNAXnVaS1qDANBgkqhkiG9w0BAQUFAAOCAQEAU/1kVZUf
|
29
|
+
wjl9bhqLZXgcKgIkzgVYwDcqFE0OdBXFD/N+oNBfV80iN/R8iCf6y4dymYDzWalD
|
30
|
+
Rho49BN531OSYbWAD0lv5/MQYDpH8uHU4cDTzV1cYkOcjFVGsO26aPM7q1SoMhf+
|
31
|
+
8tCJEl/PSHrV6JmgGRDy6YTnbQGSKPNmykEZep8wWEFXMSW9OmwaeyZyEuWUZIS4
|
32
|
+
RtAGR/Bf1/mwYLD0ZZPvsgRy0yBrTeJoaRzJXCT08cN8xBX9sa+PFsjpc267TFsv
|
33
|
+
b0cDNnwAzS78yK9xMdpD5l7/mqtfdQPVLfvra4sMBknSW3ukOP3S/WUOfKOz7Ohf
|
34
|
+
V3OoCfxVK/4Dqg==
|
35
|
+
-----END CERTIFICATE-----
|
11
36
|
|
12
|
-
date: 2010-02-
|
37
|
+
date: 2010-02-27 00:00:00 -06:00
|
13
38
|
default_executable:
|
14
39
|
dependencies: []
|
15
40
|
|
@@ -35,7 +60,6 @@ extra_rdoc_files:
|
|
35
60
|
- lib/blendris/string.rb
|
36
61
|
- lib/blendris/types.rb
|
37
62
|
- lib/blendris/utils.rb
|
38
|
-
- tasks/rspec.rake
|
39
63
|
files:
|
40
64
|
- History.txt
|
41
65
|
- Manifest
|
@@ -60,6 +84,7 @@ files:
|
|
60
84
|
- script/console
|
61
85
|
- script/destroy
|
62
86
|
- script/generate
|
87
|
+
- spec/integer_spec.rb
|
63
88
|
- spec/list_spec.rb
|
64
89
|
- spec/model_spec.rb
|
65
90
|
- spec/redis-tools_spec.rb
|
@@ -68,7 +93,6 @@ files:
|
|
68
93
|
- spec/spec.opts
|
69
94
|
- spec/spec_helper.rb
|
70
95
|
- spec/string_spec.rb
|
71
|
-
- tasks/rspec.rake
|
72
96
|
- blendris.gemspec
|
73
97
|
has_rdoc: true
|
74
98
|
homepage: http://github.com/alexmchale/blendris
|
@@ -88,18 +112,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
112
|
requirements:
|
89
113
|
- - ">="
|
90
114
|
- !ruby/object:Gem::Version
|
115
|
+
segments:
|
116
|
+
- 0
|
91
117
|
version: "0"
|
92
|
-
version:
|
93
118
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
119
|
requirements:
|
95
120
|
- - ">="
|
96
121
|
- !ruby/object:Gem::Version
|
122
|
+
segments:
|
123
|
+
- 1
|
124
|
+
- 2
|
97
125
|
version: "1.2"
|
98
|
-
version:
|
99
126
|
requirements: []
|
100
127
|
|
101
128
|
rubyforge_project: blendris
|
102
|
-
rubygems_version: 1.3.
|
129
|
+
rubygems_version: 1.3.6
|
103
130
|
signing_key:
|
104
131
|
specification_version: 3
|
105
132
|
summary: A redis library for Ruby
|
metadata.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
���C:��F�E�����8���t6?��9CI�������X=�4�ƨ�[i1b���no�X�������pE�`����C��2�aօ�N�P5�~xuX�M�n|8Qڷ��iR�G�ɕ�܋fD������bq�A������������iB%�OV�ެ�0DF����-J@�}�4�-�#ū�M�8l�;^���h�7b�_�5T6)����q������K�����q^�>n�����z{�S��rJpK����
|
data/tasks/rspec.rake
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'spec'
|
3
|
-
rescue LoadError
|
4
|
-
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
-
require 'spec'
|
6
|
-
end
|
7
|
-
begin
|
8
|
-
require 'spec/rake/spectask'
|
9
|
-
rescue LoadError
|
10
|
-
puts <<-EOS
|
11
|
-
To use rspec for testing you must install rspec gem:
|
12
|
-
gem install rspec
|
13
|
-
EOS
|
14
|
-
exit(0)
|
15
|
-
end
|
16
|
-
|
17
|
-
desc "Run the specs under spec/models"
|
18
|
-
Spec::Rake::SpecTask.new do |t|
|
19
|
-
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
-
end
|