cohitre-relaxdb 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.textile +164 -0
- data/Rakefile +52 -0
- data/docs/spec_results.html +604 -0
- data/lib/more/grapher.rb +48 -0
- data/lib/relaxdb.rb +38 -0
- data/lib/relaxdb/all_delegator.rb +48 -0
- data/lib/relaxdb/belongs_to_proxy.rb +29 -0
- data/lib/relaxdb/design_doc.rb +50 -0
- data/lib/relaxdb/document.rb +386 -0
- data/lib/relaxdb/extlib.rb +3 -0
- data/lib/relaxdb/has_many_proxy.rb +81 -0
- data/lib/relaxdb/has_one_proxy.rb +45 -0
- data/lib/relaxdb/paginate_params.rb +54 -0
- data/lib/relaxdb/paginator.rb +78 -0
- data/lib/relaxdb/query.rb +74 -0
- data/lib/relaxdb/references_many_proxy.rb +99 -0
- data/lib/relaxdb/relaxdb.rb +157 -0
- data/lib/relaxdb/server.rb +132 -0
- data/lib/relaxdb/sorted_by_view.rb +62 -0
- data/lib/relaxdb/uuid_generator.rb +21 -0
- data/lib/relaxdb/view_object.rb +34 -0
- data/lib/relaxdb/view_result.rb +18 -0
- data/lib/relaxdb/view_uploader.rb +47 -0
- data/lib/relaxdb/views.rb +42 -0
- data/spec/belongs_to_spec.rb +80 -0
- data/spec/callbacks_spec.rb +64 -0
- data/spec/denormalisation_spec.rb +49 -0
- data/spec/design_doc_spec.rb +34 -0
- data/spec/document_spec.rb +364 -0
- data/spec/has_many_spec.rb +147 -0
- data/spec/has_one_spec.rb +128 -0
- data/spec/query_spec.rb +80 -0
- data/spec/references_many_spec.rb +141 -0
- data/spec/relaxdb_spec.rb +137 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/spec_models.rb +130 -0
- data/spec/view_object_spec.rb +47 -0
- metadata +119 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
# Experimental only for now
|
4
|
+
|
5
|
+
class Tree < RelaxDB::Document
|
6
|
+
property :name
|
7
|
+
property :climate
|
8
|
+
has_one :leaf
|
9
|
+
end
|
10
|
+
|
11
|
+
class Leaf < RelaxDB::Document
|
12
|
+
belongs_to :tree, :denormalise => [:name]
|
13
|
+
end
|
14
|
+
|
15
|
+
describe RelaxDB::Document, "denormalisation" do
|
16
|
+
|
17
|
+
before(:all) do
|
18
|
+
RelaxDB.configure(:host => "localhost", :port => 5984)
|
19
|
+
end
|
20
|
+
|
21
|
+
before(:each) do
|
22
|
+
RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
|
23
|
+
RelaxDB.use_db "relaxdb_spec_db"
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "belongs_to" do
|
27
|
+
|
28
|
+
it "should store denormalised options in its json representation" do
|
29
|
+
tree = Tree.new(:name => "sapling").save
|
30
|
+
leaf = Leaf.new(:tree => tree)
|
31
|
+
obj = JSON.parse(leaf.to_json)
|
32
|
+
obj["tree_name"].should == "sapling"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should ignore denormalised options for nil properties" do
|
36
|
+
Leaf.new.to_json
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not interfere with normal belongs_to behaviour" do
|
40
|
+
tree = Tree.new(:name => "sapling", :climate => "tropical").save
|
41
|
+
leaf = Leaf.new(:tree => tree).save
|
42
|
+
leaf = RelaxDB.load(leaf._id)
|
43
|
+
leaf.tree.name.should == "sapling"
|
44
|
+
leaf.tree.climate.should == "tropical"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/spec_models.rb'
|
3
|
+
|
4
|
+
describe RelaxDB::DesignDocument do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
RelaxDB.configure(:host => "localhost", :port => 5984)
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
|
12
|
+
RelaxDB.use_db "relaxdb_spec_db"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#save" do
|
16
|
+
|
17
|
+
it "should create a corresponding document in CouchDB" do
|
18
|
+
RelaxDB::DesignDocument.get("foo").save
|
19
|
+
RelaxDB.load("_design%2Ffoo").should_not be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#destroy" do
|
25
|
+
|
26
|
+
it "should delete the corresponding document from CouchDB" do
|
27
|
+
dd = RelaxDB::DesignDocument.get("foo").save
|
28
|
+
dd.destroy!
|
29
|
+
lambda { RelaxDB.load("_design%2Ffoo") }.should raise_error
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,364 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/spec_models.rb'
|
3
|
+
|
4
|
+
describe RelaxDB::Document do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
RelaxDB.configure(:host => "localhost", :port => 5984)
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
|
12
|
+
RelaxDB.use_db "relaxdb_spec_db"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe ".new" do
|
16
|
+
|
17
|
+
it "should create an object with an id" do
|
18
|
+
Atom.new._id.should_not be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should create an object with a nil revision" do
|
22
|
+
Atom.new._rev.should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should convert attributes that end in _at to dates" do
|
26
|
+
now = Time.now
|
27
|
+
p = Post.new(:viewed_at => now).save
|
28
|
+
p = RelaxDB.load(p._id)
|
29
|
+
p.viewed_at.class.should == Time
|
30
|
+
p.viewed_at.should be_close(now, 1)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "will silently ignore parameters that don't specify class attributes" do
|
34
|
+
# Consider this a feature or bug. It allows an object containing both request params
|
35
|
+
# and superflous data to be passed directly to a constructor.
|
36
|
+
Post.new(:foo => "").save
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#to_json" do
|
42
|
+
|
43
|
+
it "should not output nil attributes" do
|
44
|
+
Atom.new.to_json.should_not include("rev")
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#save" do
|
50
|
+
|
51
|
+
it "should set an object's revision" do
|
52
|
+
p = Atom.new.save
|
53
|
+
p._rev.should_not be_nil
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should result in an object considered saved" do
|
57
|
+
Atom.new.save.should_not be_unsaved
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be invokable multiple times" do
|
61
|
+
p = Atom.new
|
62
|
+
p.save
|
63
|
+
p.save
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should set created_at when first saved" do
|
67
|
+
now = Time.now
|
68
|
+
created_at = Post.new.save.created_at
|
69
|
+
now.should be_close(created_at, 1)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should set created_at when first saved unless supplied to the constructor" do
|
73
|
+
back_then = Time.now - 1000
|
74
|
+
p = Post.new(:created_at => back_then).save
|
75
|
+
p.created_at.should be_close(back_then, 1)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "user defined property reader" do
|
81
|
+
|
82
|
+
it "should not effect normal operation" do
|
83
|
+
o = BespokeReader.new(:val => 101).save
|
84
|
+
o = RelaxDB.load o._id
|
85
|
+
o.val.should == 106
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should not modify internal state" do
|
89
|
+
o = BespokeReader.new(:val => 101).save
|
90
|
+
o = RelaxDB.load o._id
|
91
|
+
o.instance_variable_get(:@val).should == 101
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "user defined property writer" do
|
97
|
+
|
98
|
+
it "should not be used" do
|
99
|
+
o = BespokeWriter.new(:val => 101).save
|
100
|
+
o = RelaxDB.load o._id
|
101
|
+
o.val.should == 81
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "loaded objects" do
|
107
|
+
|
108
|
+
it "should contain state as when saved" do
|
109
|
+
now = Time.now
|
110
|
+
p = Primitives.new(:str => "foo", :num => 19.30, :true_bool => true, :false_bool => false, :created_at => now).save
|
111
|
+
p = RelaxDB.load(p._id)
|
112
|
+
p.str.should == "foo"
|
113
|
+
p.num.should == 19.30
|
114
|
+
p.true_bool.should be_true
|
115
|
+
p.false_bool.should_not be_true
|
116
|
+
p.created_at.should be_close(now, 1)
|
117
|
+
p.empty.should be_nil
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should be saveable" do
|
121
|
+
a = Atom.new.save
|
122
|
+
a = RelaxDB.load(a._id)
|
123
|
+
a.save
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "#destroy" do
|
129
|
+
|
130
|
+
it "should delete the corresponding document from CouchDB" do
|
131
|
+
p = Atom.new.save.destroy!
|
132
|
+
lambda { RelaxDB.load(p._id) }.should raise_error
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should prevent the object from being resaved" do
|
136
|
+
p = Atom.new.save.destroy!
|
137
|
+
lambda { p.save }.should raise_error
|
138
|
+
end
|
139
|
+
|
140
|
+
it "will result in undefined behaviour when invoked on unsaved objects" do
|
141
|
+
lambda { Atom.new.destroy! }.should raise_error
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#all.destroy!" do
|
147
|
+
|
148
|
+
it "should delete from CouchDB all documents of the corresponding class" do
|
149
|
+
Atom.new.save
|
150
|
+
Post.new.save
|
151
|
+
Post.new.save
|
152
|
+
Post.all.destroy!
|
153
|
+
Post.all.should be_empty
|
154
|
+
Atom.all.size.should == 1
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "==" do
|
160
|
+
|
161
|
+
it "should define equality based on CouchDB id" do
|
162
|
+
i1 = Atom.new.save
|
163
|
+
i2 = Atom.new.save
|
164
|
+
i3 = RelaxDB.load(i1._id)
|
165
|
+
i1.should_not == i2
|
166
|
+
i1.should == i3
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should return false when passed a nil object" do
|
170
|
+
(Atom.new == nil).should_not be_true
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
describe ".all" do
|
176
|
+
|
177
|
+
it "should return all instances of that class" do
|
178
|
+
Photo.new.save
|
179
|
+
Rating.new.save
|
180
|
+
Rating.new.save
|
181
|
+
Rating.all.size.should == 2
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should return an empty array when no instances exist" do
|
185
|
+
Atom.all.should be_an_instance_of(Array)
|
186
|
+
Atom.all.should be_empty
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
describe ".all.sorted_by" do
|
192
|
+
|
193
|
+
it "should sort ascending by default" do
|
194
|
+
Post.new(:content => "b").save
|
195
|
+
Post.new(:content => "a").save
|
196
|
+
posts = Post.all.sorted_by(:content)
|
197
|
+
posts[0].content.should == "a"
|
198
|
+
posts[1].content.should == "b"
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should sort desc when specified" do
|
202
|
+
Post.new(:content => "a").save
|
203
|
+
Post.new(:content => "b").save
|
204
|
+
posts = Post.all.sorted_by(:content) { |q| q.descending(true) }
|
205
|
+
posts[0].content.should == "b"
|
206
|
+
posts[1].content.should == "a"
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should sort date attributes lexicographically" do
|
210
|
+
t = Time.new
|
211
|
+
Post.new(:viewed_at => t+1000, :content => "late").save
|
212
|
+
Post.new(:viewed_at => t, :content => "early").save
|
213
|
+
posts = Post.all.sorted_by(:viewed_at)
|
214
|
+
posts[0].content.should == "early"
|
215
|
+
posts[1].content.should == "late"
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "results" do
|
219
|
+
|
220
|
+
it "should be retrievable by exact criteria" do
|
221
|
+
Post.new(:subject => "foo").save
|
222
|
+
Post.new(:subject => "foo").save
|
223
|
+
Post.new(:subject => "bar").save
|
224
|
+
Post.all.sorted_by(:subject) { |q| q.key("foo") }.size.should == 2
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should be retrievable by relative criteria" do
|
228
|
+
Rating.new(:stars => 1).save
|
229
|
+
Rating.new(:stars => 5).save
|
230
|
+
Rating.all.sorted_by(:stars) { |q| q.endkey(3) }.size.should == 1
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should be retrievable by combined criteria" do
|
234
|
+
User.new(:name => "paul", :age => 28).save
|
235
|
+
User.new(:name => "paul", :age => 72).save
|
236
|
+
User.new(:name => "atlas", :age => 99).save
|
237
|
+
User.all.sorted_by(:name, :age) { |q| q.startkey(["paul",0 ]).endkey(["paul", 50]) }.size.should == 1
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should be retrievable by combined criteria where not all docs contain all attributes" do
|
241
|
+
User.new(:name => "paul", :age => 28).save
|
242
|
+
User.new(:name => "paul", :age => 72).save
|
243
|
+
User.new(:name => "atlas").save
|
244
|
+
User.all.sorted_by(:name, :age) { |q| q.startkey(["paul",0 ]).endkey(["paul", 50]) }.size.should == 1
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should be retrievable by a multi key post" do
|
248
|
+
5.times { |i| Primitives.new(:num => i).save }
|
249
|
+
ps = Primitives.all.sorted_by(:num) { |q| q.keys([0, 4]) }
|
250
|
+
ps.map { |p| p.num }.should == [0, 4]
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
describe "defaults" do
|
258
|
+
|
259
|
+
it "should be set on initialisation" do
|
260
|
+
r = Rating.new
|
261
|
+
r.stars.should == 5
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should be saved" do
|
265
|
+
r = Rating.new.save
|
266
|
+
RelaxDB.load(r._id).stars.should == 5
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should be ignored once overwritten" do
|
270
|
+
r = Rating.new
|
271
|
+
r.stars = nil
|
272
|
+
r.save
|
273
|
+
RelaxDB.load(r._id).stars.should be_nil
|
274
|
+
end
|
275
|
+
|
276
|
+
it "may be a simple value" do
|
277
|
+
simple = Class.new(RelaxDB::Document) do
|
278
|
+
property :foo, :default => :bar
|
279
|
+
end
|
280
|
+
simple.new.foo.should == :bar
|
281
|
+
end
|
282
|
+
|
283
|
+
it "may be a proc" do
|
284
|
+
simple = Class.new(RelaxDB::Document) do
|
285
|
+
property :foo, :default => lambda { :bar }
|
286
|
+
end
|
287
|
+
simple.new.foo.should == :bar
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "validator" do
|
293
|
+
|
294
|
+
it "should prevent an object from being saved if it evaluates to false" do
|
295
|
+
r = Class.new(RelaxDB::Document) do
|
296
|
+
property :thumbs_up, :validator => lambda { false }
|
297
|
+
end
|
298
|
+
r.new.save.should be_false
|
299
|
+
end
|
300
|
+
|
301
|
+
it "should prevent an object from being saved if it throws an exception" do
|
302
|
+
r = Class.new(RelaxDB::Document) do
|
303
|
+
property :thumbs_up, :validator => lambda { raise "foo" }
|
304
|
+
end
|
305
|
+
r.new.save.should be_false
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should pass the property value to the validator" do
|
309
|
+
r = Class.new(RelaxDB::Document) do
|
310
|
+
property :thumbs_up, :validator => lambda { |tu| tu >=0 && tu < 3 }
|
311
|
+
end
|
312
|
+
r.new(:thumbs_up => 2).save.should be
|
313
|
+
r.new(:thumbs_up => 3).save.should be_false
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should add the validation error message if supplied, on failure" do
|
317
|
+
r = Class.new(RelaxDB::Document) do
|
318
|
+
property :thumbs_up, :validator => lambda { false }, :validation_msg => "Too many thumbs"
|
319
|
+
end
|
320
|
+
x = r.new
|
321
|
+
x.save
|
322
|
+
x.errors[:thumbs_up].should == "Too many thumbs"
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should perform all validations" do
|
326
|
+
r = Class.new(RelaxDB::Document) do
|
327
|
+
property :foo, :validator => lambda { false }, :validation_msg => "oof"
|
328
|
+
property :bar, :validator => lambda { false }, :validation_msg => "rab"
|
329
|
+
end
|
330
|
+
x = r.new
|
331
|
+
x.save
|
332
|
+
x.errors[:foo].should == "oof"
|
333
|
+
x.errors[:bar].should == "rab"
|
334
|
+
end
|
335
|
+
|
336
|
+
it "should prevent saving unless all validations pass" do
|
337
|
+
r = Class.new(RelaxDB::Document) do
|
338
|
+
property :foo, :validator => lambda { false }
|
339
|
+
property :bar, :validator => lambda { true }
|
340
|
+
end
|
341
|
+
x = r.new
|
342
|
+
x.save.should == false
|
343
|
+
end
|
344
|
+
|
345
|
+
it "may be a proc" do
|
346
|
+
r = Class.new(RelaxDB::Document) do
|
347
|
+
property :thumbs_up, :validator => lambda { false }
|
348
|
+
end
|
349
|
+
r.new.save.should be_false
|
350
|
+
end
|
351
|
+
|
352
|
+
it "may be a method" do
|
353
|
+
r = Class.new(RelaxDB::Document) do
|
354
|
+
property :thumbs_up, :validator => :count_em
|
355
|
+
def count_em
|
356
|
+
false
|
357
|
+
end
|
358
|
+
end
|
359
|
+
r.new.save.should be_false
|
360
|
+
end
|
361
|
+
|
362
|
+
end
|
363
|
+
|
364
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/spec_models.rb'
|
3
|
+
|
4
|
+
describe RelaxDB::HasManyProxy do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
RelaxDB.configure(:host => "localhost", :port => 5984)
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
RelaxDB.delete_db "relaxdb_spec_db" rescue "ok"
|
12
|
+
RelaxDB.use_db "relaxdb_spec_db"
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "has_many" do
|
16
|
+
|
17
|
+
it "should be considered enumerable" do
|
18
|
+
u = User.new.save
|
19
|
+
u.items.should be_a_kind_of( Enumerable)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should actually be enumerable" do
|
23
|
+
u = User.new.save
|
24
|
+
u.items << Item.new(:name => "a")
|
25
|
+
u.items << Item.new(:name => "b")
|
26
|
+
names = u.items.inject("") { |memo, i| memo << i.name }
|
27
|
+
names.should == "ab"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should preserve the collection across the load / save boundary" do
|
31
|
+
u = User.new.save
|
32
|
+
u.items << Item.new
|
33
|
+
u = RelaxDB.load u._id
|
34
|
+
u.items.size.should == 1
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should work with MultiWordClassNames" do
|
38
|
+
c = MultiWordChild.new
|
39
|
+
m = MultiWordClass.new.save
|
40
|
+
m.multi_word_children << c
|
41
|
+
m = RelaxDB.load m._id
|
42
|
+
m.multi_word_children[0].should == c
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#<<" do
|
46
|
+
|
47
|
+
it "should link the added item to the parent" do
|
48
|
+
u = User.new
|
49
|
+
u.items << Item.new
|
50
|
+
u.items[0].user.should == u
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return self" do
|
54
|
+
u = User.new.save
|
55
|
+
u.items << Item.new << Item.new
|
56
|
+
u.items[0].user.should == u
|
57
|
+
u.items[1].user.should == u
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not created duplicates when invoked with same object more than once" do
|
61
|
+
u = User.new.save
|
62
|
+
i = Item.new
|
63
|
+
u.items << i << i
|
64
|
+
u.items.size.should == 1
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return false when the child fails validation" do
|
68
|
+
d = Dysfunctional.new
|
69
|
+
r = (d.failures << Failure.new)
|
70
|
+
r.should be_false
|
71
|
+
d.failures.should be_empty
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#=" do
|
77
|
+
|
78
|
+
it "should fail" do
|
79
|
+
# This may be implemented in future
|
80
|
+
lambda { User.new.items = [] }.should raise_error
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#delete" do
|
86
|
+
|
87
|
+
it "should nullify the belongs_to relationship" do
|
88
|
+
u = User.new.save
|
89
|
+
i = Item.new
|
90
|
+
u.items << i
|
91
|
+
u.items.delete i
|
92
|
+
i.user.should be_nil
|
93
|
+
RelaxDB.load(i._id).user.should be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#clear" do
|
99
|
+
|
100
|
+
it "should result in an empty collection" do
|
101
|
+
u = User.new.save
|
102
|
+
u.items << Item.new << Item.new
|
103
|
+
u.items.clear
|
104
|
+
u.items.should be_empty
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should nullify all child relationships" do
|
108
|
+
u = User.new.save
|
109
|
+
i1, i2 = Item.new, Item.new
|
110
|
+
u.items << i1
|
111
|
+
u.items << i2
|
112
|
+
u.items.clear
|
113
|
+
|
114
|
+
i1.user.should be_nil
|
115
|
+
i2.user.should be_nil
|
116
|
+
RelaxDB.load(i1._id).user.should be_nil
|
117
|
+
RelaxDB.load(i2._id).user.should be_nil
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "owner" do
|
123
|
+
|
124
|
+
it "should be able to form multiple relationships with the same class of child" do
|
125
|
+
u1, u2 = User.new.save, User.new.save
|
126
|
+
i = Invite.new(:recipient => u2)
|
127
|
+
u1.invites_sent << Invite.new
|
128
|
+
RelaxDB.load(u1._id).invites_sent[0] == i
|
129
|
+
RelaxDB.load(u2._id).invites_received[0] == i
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#destroy" do
|
133
|
+
|
134
|
+
it "should nullify its child relationships" do
|
135
|
+
u = User.new.save
|
136
|
+
u.items << Item.new << Item.new
|
137
|
+
u.destroy!
|
138
|
+
Item.all.sorted_by(:user_id) { |q| q.key(u._id) }.should be_empty
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|