blendris 0.5 → 0.6

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.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