relaxdb 0.3.5
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 +200 -0
- data/Rakefile +63 -0
- data/docs/spec_results.html +1059 -0
- data/lib/more/atomic_bulk_save_support.rb +18 -0
- data/lib/more/grapher.rb +48 -0
- data/lib/relaxdb.rb +50 -0
- data/lib/relaxdb/all_delegator.rb +44 -0
- data/lib/relaxdb/belongs_to_proxy.rb +29 -0
- data/lib/relaxdb/design_doc.rb +57 -0
- data/lib/relaxdb/document.rb +600 -0
- data/lib/relaxdb/extlib.rb +24 -0
- data/lib/relaxdb/has_many_proxy.rb +101 -0
- data/lib/relaxdb/has_one_proxy.rb +42 -0
- data/lib/relaxdb/migration.rb +40 -0
- data/lib/relaxdb/migration_version.rb +21 -0
- data/lib/relaxdb/net_http_server.rb +61 -0
- data/lib/relaxdb/paginate_params.rb +53 -0
- data/lib/relaxdb/paginator.rb +88 -0
- data/lib/relaxdb/query.rb +76 -0
- data/lib/relaxdb/references_many_proxy.rb +97 -0
- data/lib/relaxdb/relaxdb.rb +250 -0
- data/lib/relaxdb/server.rb +109 -0
- data/lib/relaxdb/taf2_curb_server.rb +63 -0
- data/lib/relaxdb/uuid_generator.rb +21 -0
- data/lib/relaxdb/validators.rb +11 -0
- data/lib/relaxdb/view_object.rb +34 -0
- data/lib/relaxdb/view_result.rb +18 -0
- data/lib/relaxdb/view_uploader.rb +49 -0
- data/lib/relaxdb/views.rb +114 -0
- data/readme.rb +80 -0
- data/spec/belongs_to_spec.rb +124 -0
- data/spec/callbacks_spec.rb +80 -0
- data/spec/derived_properties_spec.rb +112 -0
- data/spec/design_doc_spec.rb +34 -0
- data/spec/doc_inheritable_spec.rb +100 -0
- data/spec/document_spec.rb +545 -0
- data/spec/has_many_spec.rb +202 -0
- data/spec/has_one_spec.rb +123 -0
- data/spec/migration_spec.rb +97 -0
- data/spec/migration_version_spec.rb +28 -0
- data/spec/paginate_params_spec.rb +15 -0
- data/spec/paginate_spec.rb +360 -0
- data/spec/query_spec.rb +90 -0
- data/spec/references_many_spec.rb +173 -0
- data/spec/relaxdb_spec.rb +364 -0
- data/spec/server_spec.rb +32 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +65 -0
- data/spec/spec_models.rb +199 -0
- data/spec/view_by_spec.rb +76 -0
- data/spec/view_object_spec.rb +47 -0
- data/spec/view_spec.rb +23 -0
- metadata +137 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/spec_models.rb'
|
3
|
+
|
4
|
+
describe RelaxDB::ReferencesManyProxy do
|
5
|
+
|
6
|
+
before(:all) do
|
7
|
+
setup_test_db
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "references_many" do
|
11
|
+
|
12
|
+
it "should preserve the relationships across the save / load boundary" do
|
13
|
+
p = Photo.new
|
14
|
+
t = Tag.new
|
15
|
+
t.photos << p
|
16
|
+
|
17
|
+
p = RelaxDB.load p._id
|
18
|
+
p.tags.size.should == 1
|
19
|
+
p.tags[0].should == t
|
20
|
+
|
21
|
+
t = RelaxDB.load t._id
|
22
|
+
t.photos.size.should == 1
|
23
|
+
t.photos[0].should == p
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should issue only a single request to resolve the relationship" do
|
27
|
+
p, t = Photo.new, Tag.new
|
28
|
+
p.tags << t
|
29
|
+
|
30
|
+
# Create the views
|
31
|
+
p.tags.map { |t| t._id }
|
32
|
+
|
33
|
+
p = RelaxDB.load p._id
|
34
|
+
RelaxDB.db.get_count = 0
|
35
|
+
p.tags.map { |t| t._id }
|
36
|
+
p.tags.map { |t| t._id }
|
37
|
+
RelaxDB.db.get_count.should == 1
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not resolve the relationship when an object is instantiated" do
|
41
|
+
p, t = Photo.new, Tag.new
|
42
|
+
p.tags << t
|
43
|
+
|
44
|
+
RelaxDB.db.get_count = 0
|
45
|
+
p = RelaxDB.load p._id
|
46
|
+
RelaxDB.db.get_count.should == 1
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should make the ids available as a property" do
|
50
|
+
p, t = Photo.new, Tag.new
|
51
|
+
p.tags << t
|
52
|
+
|
53
|
+
p.tags_ids.should == [t._id]
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#=" do
|
57
|
+
it "should not be invoked" do
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#<<" do
|
62
|
+
|
63
|
+
it "should set the relationship on both sides" do
|
64
|
+
p = Photo.new(:name => "photo")
|
65
|
+
t = Tag.new(:name => "tag")
|
66
|
+
p.tags << t
|
67
|
+
|
68
|
+
p.tags.size.should == 1
|
69
|
+
p.tags[0].name.should == "tag"
|
70
|
+
|
71
|
+
t.photos.size.should == 1
|
72
|
+
t.photos[0].name.should == "photo"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should not create duplicates when the same object is added more than once" do
|
76
|
+
p = Photo.new
|
77
|
+
t = Tag.new
|
78
|
+
p.tags << t << t
|
79
|
+
p.tags.size.should == 1
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should not create duplicates when reciprocal objects are added from opposite sides" do
|
83
|
+
p = Photo.new
|
84
|
+
t = Tag.new
|
85
|
+
p.tags << t
|
86
|
+
t.photos << p
|
87
|
+
p.tags.size.should == 1
|
88
|
+
t.photos.size.should == 1
|
89
|
+
end
|
90
|
+
|
91
|
+
it "will resolve the reciprocal relationship" do
|
92
|
+
# Create the views
|
93
|
+
p, t = Photo.new, Tag.new
|
94
|
+
p.tags << t
|
95
|
+
|
96
|
+
p, t = Photo.new, Tag.new
|
97
|
+
RelaxDB.db.get_count = 0
|
98
|
+
p.tags << t
|
99
|
+
RelaxDB.db.get_count.should == 2
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "#delete" do
|
105
|
+
|
106
|
+
it "should nullify relationship on both sides" do
|
107
|
+
p = Photo.new
|
108
|
+
t = Tag.new
|
109
|
+
p.tags << t
|
110
|
+
|
111
|
+
p.tags.delete(t)
|
112
|
+
p.tags.should be_empty
|
113
|
+
t.photos.should be_empty
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "owner#destroy" do
|
119
|
+
|
120
|
+
it "should remove its membership from its peers in memory" do
|
121
|
+
p = Photo.new
|
122
|
+
t = Tag.new
|
123
|
+
p.tags << t
|
124
|
+
|
125
|
+
p.destroy!
|
126
|
+
t.photos.size.should == 0
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should remove its membership from its peers in CouchDB" do
|
130
|
+
p = Photo.new
|
131
|
+
t = Tag.new
|
132
|
+
p.tags << t
|
133
|
+
|
134
|
+
p.destroy!
|
135
|
+
RelaxDB.load(t._id).photos.should be_empty
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
# Leaving this test as a reminder of problems with all.destroy and a self referential
|
141
|
+
# references_many
|
142
|
+
#
|
143
|
+
# This test more complex than it needs to be to prove the point
|
144
|
+
# It also serves as a proof of a self referential references_many, but there are better places for that
|
145
|
+
# it "all.destroy should play nice with self referential references_many" do
|
146
|
+
# u1 = TwitterUser.new(:name => "u1")
|
147
|
+
# u2 = TwitterUser.new(:name => "u2")
|
148
|
+
# u3 = TwitterUser.new(:name => "u3")
|
149
|
+
#
|
150
|
+
# u1.followers << u2
|
151
|
+
# u1.followers << u3
|
152
|
+
# u3.leaders << u2
|
153
|
+
#
|
154
|
+
# u1f = u1.followers.map { |u| u.name }
|
155
|
+
# u1f.sort.should == ["u2", "u3"]
|
156
|
+
# u1.leaders.should be_empty
|
157
|
+
#
|
158
|
+
# u2.leaders.size.should == 1
|
159
|
+
# u2.leaders[0].name.should == "u1"
|
160
|
+
# u2.followers.size.should == 1
|
161
|
+
# u2.followers[0].name.should == "u3"
|
162
|
+
#
|
163
|
+
# u3l = u3.leaders.map { |u| u.name }
|
164
|
+
# u3l.sort.should == ["u1", "u2"]
|
165
|
+
# u3.followers.should be_empty
|
166
|
+
#
|
167
|
+
# TwitterUser.all.destroy!
|
168
|
+
# TwitterUser.all.should be_empty
|
169
|
+
# end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
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 do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
setup_test_db
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".create_object" do
|
11
|
+
|
12
|
+
it "should return an instance of a known object if passed a hash with a class key" do
|
13
|
+
data = { "relaxdb_class" => "Item" }
|
14
|
+
obj = RelaxDB.create_object(data)
|
15
|
+
obj.should be_instance_of(Item)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should return an instance of a dynamically created object if no class key is provided" do
|
19
|
+
data = { "name" => "tesla coil", "strength" => 5000 }
|
20
|
+
obj = RelaxDB.create_object(data)
|
21
|
+
obj.name.should == "tesla coil"
|
22
|
+
obj.strength.should == 5000
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# bulk_save and bulk_save! should match Document#save and Document#save! semantics
|
28
|
+
describe ".bulk_save" do
|
29
|
+
|
30
|
+
it "should be invokable multiple times" do
|
31
|
+
t1, t2 = Tag.new, Tag.new
|
32
|
+
RelaxDB.bulk_save(t1, t2)
|
33
|
+
RelaxDB.bulk_save(t1, t2)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return the objects it was passed" do
|
37
|
+
t1, t2 = Tag.new, Tag.new
|
38
|
+
ta, tb = RelaxDB.bulk_save(t1, t2)
|
39
|
+
ta.should == t1
|
40
|
+
tb.should == t2
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should return false on failure" do
|
44
|
+
c = Class.new(RelaxDB::Document) do
|
45
|
+
property :foo, :validator => lambda { false }
|
46
|
+
end
|
47
|
+
x = c.new
|
48
|
+
RelaxDB.bulk_save(x).should be_false
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not attempt to save if a pre-save stage fails" do
|
52
|
+
c = Class.new(RelaxDB::Document) do
|
53
|
+
property :foo, :validator => lambda { false }
|
54
|
+
end
|
55
|
+
x = c.new
|
56
|
+
RelaxDB.bulk_save(x)
|
57
|
+
x.should be_new_document
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should invoke the after-save stage after a successful save" do
|
61
|
+
c = Class.new(RelaxDB::Document) do
|
62
|
+
attr_accessor :foo
|
63
|
+
after_save lambda { |c| c.foo = :bar }
|
64
|
+
end
|
65
|
+
x = c.new
|
66
|
+
RelaxDB.bulk_save(x).first.foo.should == :bar
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should save non conflicting docs and mark conflicting docs" do
|
70
|
+
p1, p2 = Atom.new.save!, Atom.new.save!
|
71
|
+
p1.dup.save!
|
72
|
+
RelaxDB.bulk_save p1, p2
|
73
|
+
p1._rev.should =~ /1-/
|
74
|
+
p1.should be_update_conflict
|
75
|
+
p2._rev.should =~ /2-/
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# This spec is as much a verification of my understanding of
|
80
|
+
# bulk_save semantics as it is a test of RelaxDB
|
81
|
+
#
|
82
|
+
# See http://mail-archives.apache.org/mod_mbox/couchdb-dev/200905.mbox/%3CF476A3D8-8F50-40A0-8668-C00D72196FBA@apache.org%3E
|
83
|
+
# for an explanation of the final section
|
84
|
+
#
|
85
|
+
describe "all-or-nothing" do
|
86
|
+
it "should save non conflicting and conflicting docs" do
|
87
|
+
p1, p2 = Primitives.new(:num => 1).save!, Primitives.new(:num => 2).save!
|
88
|
+
p1d = p1.dup
|
89
|
+
p1d.num = 11
|
90
|
+
p1d.save!
|
91
|
+
p1.num = 6
|
92
|
+
RelaxDB.bulk_save :all_or_nothing, p1, p2
|
93
|
+
p1._rev.should =~ /2-/
|
94
|
+
p2._rev.should =~ /2-/
|
95
|
+
|
96
|
+
p1 = RelaxDB.load p1._id, :conflicts => true
|
97
|
+
p1n1 = p1.num
|
98
|
+
p1 = RelaxDB.load p1._id, :rev => p1._conflicts[0]
|
99
|
+
p1n2 = p1.num
|
100
|
+
if p1n1 == 11
|
101
|
+
p1n2.should == 6
|
102
|
+
else
|
103
|
+
p1n1.should == 6 && p1n2.should == 11
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# Test behind
|
109
|
+
# http://mail-archives.apache.org/mod_mbox/couchdb-dev/200905.mbox/%3CF476A3D8-8F50-40A0-8668-C00D72196FBA@apache.org%3E
|
110
|
+
# Effectively defunct
|
111
|
+
#
|
112
|
+
# it "non-deterministic winner" do
|
113
|
+
# p = Primitives.new(:num => 1).save!
|
114
|
+
# pd = p.dup
|
115
|
+
# p.num = 2
|
116
|
+
# p.save!
|
117
|
+
# pd.num = 3
|
118
|
+
# RelaxDB.bulk_save :all_or_nothing, pd
|
119
|
+
# RelaxDB.reload(p).num.should == 2
|
120
|
+
# end
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
describe ".bulk_save!" do
|
126
|
+
|
127
|
+
it "should succeed when passed no args" do
|
128
|
+
RelaxDB.bulk_save!
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should raise when passed a nil value" do
|
132
|
+
lambda do
|
133
|
+
RelaxDB.bulk_save! *[nil]
|
134
|
+
end.should raise_error
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should raise an exception if a obj fails validation" do
|
138
|
+
c = Class.new(RelaxDB::Document) do
|
139
|
+
property :foo, :validator => lambda { false }
|
140
|
+
end
|
141
|
+
lambda { RelaxDB.bulk_save!(c.new) }.should raise_error(RelaxDB::ValidationFailure)
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should raise an exception on document conflict after all docs have been processed" do
|
145
|
+
p1, p2 = Atom.new.save!, Atom.new.save!
|
146
|
+
p1.dup.save!
|
147
|
+
lambda { RelaxDB.bulk_save!(p1, p2) }.should raise_error(RelaxDB::UpdateConflict)
|
148
|
+
p2._rev.should =~ /2-/
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
describe ".db_info" do
|
154
|
+
it "should return db info" do
|
155
|
+
RelaxDB.db_info.doc_count.should == 1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe ".replicate_db" do
|
160
|
+
|
161
|
+
it "should replicate the named database" do
|
162
|
+
orig = "relaxdb_spec"
|
163
|
+
replica = "relaxdb_spec_replicate_test"
|
164
|
+
RelaxDB.delete_db replica rescue :ok
|
165
|
+
class ReplicaTest < RelaxDB::Document; end
|
166
|
+
ReplicaTest.new.save # implicitly saved to orig
|
167
|
+
RelaxDB.replicate_db orig, replica
|
168
|
+
RelaxDB.use_db replica
|
169
|
+
ReplicaTest.all.size.should == 1
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
describe ".load" do
|
175
|
+
|
176
|
+
it "should load a single document" do
|
177
|
+
a = Atom.new.save
|
178
|
+
ar = RelaxDB.load a._id
|
179
|
+
ar.should == a
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should load an arbitrary number of documents" do
|
183
|
+
a1, a2 = Atom.new.save, Atom.new.save
|
184
|
+
ar1, ar2 = RelaxDB.load [a1._id, a2._id]
|
185
|
+
ar1.should == a1
|
186
|
+
ar2.should == a2
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should return nil when given a id for a non existant doc" do
|
190
|
+
RelaxDB.load("nothere").should be_nil
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should return an array with correctly placed nils when given a list containing non existant doc ids" do
|
194
|
+
a1, a2 = Atom.new.save, Atom.new.save
|
195
|
+
res = RelaxDB.load [nil, a1._id, nil, a2._id, nil]
|
196
|
+
res.should == [nil, a1, nil, a2, nil]
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
describe ".load!" do
|
202
|
+
|
203
|
+
it "should load a single document" do
|
204
|
+
a = Atom.new.save
|
205
|
+
ar = RelaxDB.load! a._id
|
206
|
+
ar.should == a
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should load multiple documents" do
|
210
|
+
a1, a2 = Atom.new.save, Atom.new.save
|
211
|
+
ar1, ar2 = RelaxDB.load! [a1._id, a2._id]
|
212
|
+
ar1.should == a1
|
213
|
+
ar2.should == a2
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should load multiple documents in order" do
|
217
|
+
ns = (0...100).map { rand(1_000_000_000).to_s }
|
218
|
+
objs = ns.map { |n| Primitives.new :_id => n }
|
219
|
+
RelaxDB.bulk_save! *objs
|
220
|
+
ns = ns.reverse
|
221
|
+
objs = RelaxDB.load! ns
|
222
|
+
99.downto(0) do |i|
|
223
|
+
ns[i].should == objs[i]._id
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
it "should throw an exception if given a single id for a non-existant doc" do
|
228
|
+
lambda do
|
229
|
+
RelaxDB.load! "nothere"
|
230
|
+
end.should raise_error(RelaxDB::NotFound)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should throw an exception if any of a list of doc ids is for a non-existant doc" do
|
234
|
+
a = Atom.new.save
|
235
|
+
lambda do
|
236
|
+
RelaxDB.load! [nil, a._id]
|
237
|
+
end.should raise_error(RelaxDB::NotFound)
|
238
|
+
end
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
describe ".view" do
|
243
|
+
|
244
|
+
map_func = %Q<
|
245
|
+
function (doc) {
|
246
|
+
emit(doc._id, doc);
|
247
|
+
}
|
248
|
+
>
|
249
|
+
|
250
|
+
it "should request a view and return an array" do
|
251
|
+
RelaxDB::DesignDocument.get(RelaxDB.dd).add_view("simple", "map", map_func).save
|
252
|
+
data = RelaxDB.view("simple")
|
253
|
+
data.should == []
|
254
|
+
end
|
255
|
+
|
256
|
+
it "may accept query params" do
|
257
|
+
RelaxDB::DesignDocument.get(RelaxDB.dd).add_view("simple", "map", map_func).save
|
258
|
+
RelaxDB.db.put("x", {}.to_json)
|
259
|
+
RelaxDB.db.put("y", {}.to_json)
|
260
|
+
res = RelaxDB.view "simple", :key => "x"
|
261
|
+
res.first._id.should == "x"
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should be queryable with a multi key post" do
|
265
|
+
Primitives.view_by :num
|
266
|
+
|
267
|
+
5.times { |i| Primitives.new(:num => i).save }
|
268
|
+
Primitives.by_num
|
269
|
+
result = RelaxDB.view "Primitives_by_num", :keys => [0, 4], :reduce => false
|
270
|
+
result.map{ |p| p.num }.should == [0, 4]
|
271
|
+
end
|
272
|
+
|
273
|
+
it "should return nil for a reduce view with no results" do
|
274
|
+
Primitives.view_by :num
|
275
|
+
RelaxDB.view("Primitives_by_num", :reduce => true).should be_nil
|
276
|
+
end
|
277
|
+
|
278
|
+
it "should return a single value for a reduce view with a single result" do
|
279
|
+
Primitives.view_by :num
|
280
|
+
Primitives.new(:num => :x).save!
|
281
|
+
RelaxDB.view("Primitives_by_num", :reduce => true).should == 1
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should return an array for a reduce view with multiple results" do
|
285
|
+
Primitives.view_by :num
|
286
|
+
2.times { |i| Primitives.new(:num => i).save! }
|
287
|
+
res = RelaxDB.view("Primitives_by_num", :reduce => true, :group => true)
|
288
|
+
res.should be_an_instance_of(Array)
|
289
|
+
res.size.should == 2
|
290
|
+
end
|
291
|
+
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
describe ".merge" do
|
296
|
+
|
297
|
+
it "should merge rows sharing a common merge key into a single ViewObject" do
|
298
|
+
rows = [
|
299
|
+
{"value" => {"sculptor_id" => 1, "sculpture_name" => "strandbeesten"} },
|
300
|
+
{"value" => {"sculptor_id" => 1, "sculptor_name" => "hans"} },
|
301
|
+
{"value" => {"sculptor_id" => 2, "sculpture_name" => "parading dogs"} },
|
302
|
+
{"value" => {"sculptor_id" => 2, "sculptor_name" => "holmes"} }
|
303
|
+
]
|
304
|
+
data = {"rows" => rows}
|
305
|
+
result = RelaxDB.merge(data, "sculptor_id")
|
306
|
+
result = result.sort { |a, b| a.sculptor_name <=> b.sculptor_name }
|
307
|
+
|
308
|
+
result[0].sculptor_name.should == "hans"
|
309
|
+
result[0].sculpture_name.should == "strandbeesten"
|
310
|
+
result[1].sculptor_name.should == "holmes"
|
311
|
+
result[1].sculpture_name.should == "parading dogs"
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "create_views disabled" do
|
317
|
+
|
318
|
+
before(:each) do
|
319
|
+
create_test_db
|
320
|
+
RelaxDB.enable_view_creation false
|
321
|
+
|
322
|
+
class CvdBar < RelaxDB::Document
|
323
|
+
view_by :foo
|
324
|
+
has_one :foo1
|
325
|
+
has_many :foon
|
326
|
+
references_many :foor
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
it "should not create any views" do
|
331
|
+
dd = RelaxDB::DesignDocument.get "spec_doc"
|
332
|
+
dd.data["views"].should be_nil
|
333
|
+
end
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
describe "create_views enabled" do
|
338
|
+
|
339
|
+
before(:each) do
|
340
|
+
create_test_db
|
341
|
+
|
342
|
+
class CveBar < RelaxDB::Document
|
343
|
+
view_by :foo
|
344
|
+
has_one :foo1
|
345
|
+
has_many :foon
|
346
|
+
references_many :foor
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
it "should create all views" do
|
351
|
+
dd = RelaxDB::DesignDocument.get "spec_doc"
|
352
|
+
dd.data["views"]["CveBar_all"].should be
|
353
|
+
dd.data["views"]["CveBar_by_foo"].should be
|
354
|
+
dd.data["views"]["CveBar_foo1"].should be
|
355
|
+
dd.data["views"]["CveBar_foon"].should be
|
356
|
+
dd.data["views"]["CveBar_foor"].should be
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
# if caching is added
|
362
|
+
# it "should offer an example where behaviour is different with caching enabled and caching disabled"
|
363
|
+
|
364
|
+
end
|