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 ADDED
@@ -0,0 +1,2 @@
1
+ i q��T��)�6�/���‚C���#�hF�������Y"�t���%^���x�֦;�{�/J��]M�3�� �>�At*.IM�s6�'�/�:Wĩ����TSu�2�
2
+ n��/��q��5��j�+Q��
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. In the case of the employer
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
- * Note that spaces are converted to underscores, as spaces are not
69
- allowed in Redis keys. This could cause problems in some data sets.
70
- * Also note that the value assigned to the base key is the class name of
71
- the model being used.
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 maintains a set of references to other objects.
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
- * *reverse* will cause the given field to be updated on the object when
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.5") do |p|
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"
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.date = %q{2010-02-21}
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", "tasks/rspec.rake"]
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", "tasks/rspec.rake", "blendris.gemspec"]
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.5}
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
@@ -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
- RedisAccessor.redis
53
+ Blendris.redis
12
54
  end
13
55
 
14
56
  def self.redis
15
- $_redis_connection ||= Redis.new
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.cast_value symbol, value
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
- yield temporary_set
63
- temporary_set.clear
99
+
100
+ begin
101
+ yield temporary_set
102
+ ensure
103
+ temporary_set.clear
104
+ end
64
105
 
65
106
  self
66
107
  end
@@ -1,5 +1,3 @@
1
1
  module Blendris
2
2
 
3
- class BlendrisCannotSetKeyValue < Exception; end
4
-
5
3
  end
@@ -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
@@ -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
- # TODO: This can also probably go away when I remove the need for method_missing.
67
- def redis_symbol(name)
45
+ def [](name)
46
+ name = name.to_s
47
+
68
48
  subkey = self.subkey(name)
69
49
 
70
- options = self.class.redis_symbols[name.to_s]
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.redis_symbol(parm).set args[i]
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
- module RedisNode
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
@@ -5,8 +5,6 @@ module Blendris
5
5
 
6
6
  class RedisReference < RedisReferenceBase
7
7
 
8
- include RedisNode
9
-
10
8
  def ref
11
9
  @ref ||= RedisString.new(@key)
12
10
  end
@@ -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.redis_symbol(@reverse)
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.redis_symbol(@reverse)
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
- refkeys = objs.flatten.compact.map {|o| o.key}
17
- self.refs.set refkeys
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
@@ -2,9 +2,8 @@ module Blendris
2
2
 
3
3
  # RedisSet is a wrapper to the Redis SET data type.
4
4
 
5
- class RedisSet
5
+ class RedisSet < RedisNode
6
6
 
7
- include RedisNode
8
7
  include Enumerable
9
8
 
10
9
  def initialize(key, options = {})
@@ -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
- lambda { @onion.name = "asdf" }.should raise_exception(BlendrisCannotSetKeyValue)
26
- lambda { @onion.description = "asdf" }.should_not raise_exception
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
- RedisAccessor.database = 11
87
- RedisAccessor.flushdb
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
- RedisAccessor.flushdb
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
- version: "0.5"
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-21 00:00:00 -06:00
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.5
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