mattetti-couchrest 0.14.2 → 0.15
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/README.md +1 -7
- data/examples/model/example.rb +19 -13
- data/lib/couchrest/core/database.rb +1 -1
- data/lib/couchrest/more/extended_document.rb +2 -1
- data/lib/couchrest/more/property.rb +2 -0
- data/lib/couchrest.rb +1 -1
- data/spec/couchrest/core/database_spec.rb +1 -1
- data/spec/couchrest/more/extended_doc_attachment_spec.rb +129 -0
- data/spec/couchrest/more/extended_doc_spec.rb +358 -26
- data/spec/couchrest/more/extended_doc_view_spec.rb +204 -0
- data/spec/couchrest/more/property_spec.rb +16 -5
- data/spec/spec_helper.rb +4 -0
- metadata +8 -3
- data/lib/couchrest/core/model.rb +0 -615
- data/spec/couchrest/core/model_spec.rb +0 -856
@@ -1,4 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
require File.join(FIXTURE_PATH, 'more', 'article')
|
3
|
+
require File.join(FIXTURE_PATH, 'more', 'course')
|
4
|
+
|
2
5
|
|
3
6
|
describe "ExtendedDocument" do
|
4
7
|
|
@@ -41,10 +44,86 @@ describe "ExtendedDocument" do
|
|
41
44
|
end
|
42
45
|
end
|
43
46
|
|
47
|
+
class WithTemplateAndUniqueID < CouchRest::ExtendedDocument
|
48
|
+
use_database TEST_SERVER.default_database
|
49
|
+
unique_id do |model|
|
50
|
+
model['important-field']
|
51
|
+
end
|
52
|
+
property :preset, :default => 'value'
|
53
|
+
property :has_no_default
|
54
|
+
end
|
55
|
+
|
44
56
|
before(:each) do
|
45
57
|
@obj = WithDefaultValues.new
|
46
58
|
end
|
47
59
|
|
60
|
+
describe "instance database connection" do
|
61
|
+
it "should use the default database" do
|
62
|
+
@obj.database.name.should == 'couchrest-test'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should override the default db" do
|
66
|
+
@obj.database = TEST_SERVER.database!('couchrest-extendedmodel-test')
|
67
|
+
@obj.database.name.should == 'couchrest-extendedmodel-test'
|
68
|
+
@obj.database.delete!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "a new model" do
|
73
|
+
it "should be a new_record" do
|
74
|
+
@obj = Basic.new
|
75
|
+
@obj.rev.should be_nil
|
76
|
+
@obj.should be_a_new_record
|
77
|
+
end
|
78
|
+
it "should be a new_document" do
|
79
|
+
@obj = Basic.new
|
80
|
+
@obj.rev.should be_nil
|
81
|
+
@obj.should be_a_new_document
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "update attributes without saving" do
|
86
|
+
before(:each) do
|
87
|
+
a = Article.get "big-bad-danger" rescue nil
|
88
|
+
a.destroy if a
|
89
|
+
@art = Article.new(:title => "big bad danger")
|
90
|
+
@art.save
|
91
|
+
end
|
92
|
+
it "should work for attribute= methods" do
|
93
|
+
@art['title'].should == "big bad danger"
|
94
|
+
@art.update_attributes_without_saving('date' => Time.now, :title => "super danger")
|
95
|
+
@art['title'].should == "super danger"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should flip out if an attribute= method is missing" do
|
99
|
+
lambda {
|
100
|
+
@art.update_attributes_without_saving('slug' => "new-slug", :title => "super danger")
|
101
|
+
}.should raise_error
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should not change other attributes if there is an error" do
|
105
|
+
lambda {
|
106
|
+
@art.update_attributes_without_saving('slug' => "new-slug", :title => "super danger")
|
107
|
+
}.should raise_error
|
108
|
+
@art['title'].should == "big bad danger"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "update attributes" do
|
113
|
+
before(:each) do
|
114
|
+
a = Article.get "big-bad-danger" rescue nil
|
115
|
+
a.destroy if a
|
116
|
+
@art = Article.new(:title => "big bad danger")
|
117
|
+
@art.save
|
118
|
+
end
|
119
|
+
it "should save" do
|
120
|
+
@art['title'].should == "big bad danger"
|
121
|
+
@art.update_attributes('date' => Time.now, :title => "super danger")
|
122
|
+
loaded = Article.get(@art.id)
|
123
|
+
loaded['title'].should == "super danger"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
48
127
|
describe "with default" do
|
49
128
|
it "should have the default value set at initalization" do
|
50
129
|
@obj.preset.should == {:right => 10, :top_align => false}
|
@@ -67,7 +146,137 @@ describe "ExtendedDocument" do
|
|
67
146
|
end
|
68
147
|
end
|
69
148
|
|
149
|
+
describe "a doc with template values (CR::Model spec)" do
|
150
|
+
before(:all) do
|
151
|
+
WithTemplateAndUniqueID.all.map{|o| o.destroy(true)}
|
152
|
+
WithTemplateAndUniqueID.database.bulk_delete
|
153
|
+
@tmpl = WithTemplateAndUniqueID.new
|
154
|
+
@tmpl2 = WithTemplateAndUniqueID.new(:preset => 'not_value', 'important-field' => '1')
|
155
|
+
end
|
156
|
+
it "should have fields set when new" do
|
157
|
+
@tmpl.preset.should == 'value'
|
158
|
+
end
|
159
|
+
it "shouldn't override explicitly set values" do
|
160
|
+
@tmpl2.preset.should == 'not_value'
|
161
|
+
end
|
162
|
+
it "shouldn't override existing documents" do
|
163
|
+
@tmpl2.save
|
164
|
+
tmpl2_reloaded = WithTemplateAndUniqueID.get(@tmpl2.id)
|
165
|
+
@tmpl2.preset.should == 'not_value'
|
166
|
+
tmpl2_reloaded.preset.should == 'not_value'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "getting a model" do
|
171
|
+
before(:all) do
|
172
|
+
@art = Article.new(:title => 'All About Getting')
|
173
|
+
@art.save
|
174
|
+
end
|
175
|
+
it "should load and instantiate it" do
|
176
|
+
foundart = Article.get @art.id
|
177
|
+
foundart.title.should == "All About Getting"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "getting a model with a subobjects array" do
|
182
|
+
before(:all) do
|
183
|
+
course_doc = {
|
184
|
+
"title" => "Metaphysics 200",
|
185
|
+
"questions" => [
|
186
|
+
{
|
187
|
+
"q" => "Carve the ___ of reality at the ___.",
|
188
|
+
"a" => ["beast","joints"]
|
189
|
+
},{
|
190
|
+
"q" => "Who layed the smack down on Leibniz's Law?",
|
191
|
+
"a" => "Willard Van Orman Quine"
|
192
|
+
}
|
193
|
+
]
|
194
|
+
}
|
195
|
+
r = Course.database.save_doc course_doc
|
196
|
+
@course = Course.get r['id']
|
197
|
+
end
|
198
|
+
it "should load the course" do
|
199
|
+
@course.title.should == "Metaphysics 200"
|
200
|
+
end
|
201
|
+
it "should instantiate them as such" do
|
202
|
+
@course["questions"][0].a[0].should == "beast"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "finding all instances of a model" do
|
207
|
+
before(:all) do
|
208
|
+
WithTemplateAndUniqueID.all.map{|o| o.destroy(true)}
|
209
|
+
WithTemplateAndUniqueID.database.bulk_delete
|
210
|
+
WithTemplateAndUniqueID.new('important-field' => '1').save
|
211
|
+
WithTemplateAndUniqueID.new('important-field' => '2').save
|
212
|
+
WithTemplateAndUniqueID.new('important-field' => '3').save
|
213
|
+
WithTemplateAndUniqueID.new('important-field' => '4').save
|
214
|
+
end
|
215
|
+
it "should make the design doc" do
|
216
|
+
WithTemplateAndUniqueID.all
|
217
|
+
d = WithTemplateAndUniqueID.design_doc
|
218
|
+
d['views']['all']['map'].should include('WithTemplateAndUniqueID')
|
219
|
+
end
|
220
|
+
it "should find all" do
|
221
|
+
rs = WithTemplateAndUniqueID.all
|
222
|
+
rs.length.should == 4
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "finding the first instance of a model" do
|
227
|
+
before(:each) do
|
228
|
+
@db = reset_test_db!
|
229
|
+
WithTemplateAndUniqueID.new('important-field' => '1').save
|
230
|
+
WithTemplateAndUniqueID.new('important-field' => '2').save
|
231
|
+
WithTemplateAndUniqueID.new('important-field' => '3').save
|
232
|
+
WithTemplateAndUniqueID.new('important-field' => '4').save
|
233
|
+
end
|
234
|
+
it "should make the design doc" do
|
235
|
+
WithTemplateAndUniqueID.all
|
236
|
+
d = WithTemplateAndUniqueID.design_doc
|
237
|
+
d['views']['all']['map'].should include('WithTemplateAndUniqueID')
|
238
|
+
end
|
239
|
+
it "should find first" do
|
240
|
+
rs = WithTemplateAndUniqueID.first
|
241
|
+
rs['important-field'].should == "1"
|
242
|
+
end
|
243
|
+
it "should return nil if no instances are found" do
|
244
|
+
WithTemplateAndUniqueID.all.each {|obj| obj.destroy }
|
245
|
+
WithTemplateAndUniqueID.first.should be_nil
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe "getting a model with a subobject field" do
|
250
|
+
before(:all) do
|
251
|
+
course_doc = {
|
252
|
+
"title" => "Metaphysics 410",
|
253
|
+
"professor" => {
|
254
|
+
"name" => ["Mark", "Hinchliff"]
|
255
|
+
},
|
256
|
+
"final_test_at" => "2008/12/19 13:00:00 +0800"
|
257
|
+
}
|
258
|
+
r = Course.database.save_doc course_doc
|
259
|
+
@course = Course.get r['id']
|
260
|
+
end
|
261
|
+
it "should load the course" do
|
262
|
+
@course["professor"]["name"][1].should == "Hinchliff"
|
263
|
+
end
|
264
|
+
it "should instantiate the professor as a person" do
|
265
|
+
@course['professor'].last_name.should == "Hinchliff"
|
266
|
+
end
|
267
|
+
it "should instantiate the final_test_at as a Time" do
|
268
|
+
@course['final_test_at'].should == Time.parse("2008/12/19 13:00:00 +0800")
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
70
272
|
describe "timestamping" do
|
273
|
+
before(:each) do
|
274
|
+
oldart = Article.get "saving-this" rescue nil
|
275
|
+
oldart.destroy if oldart
|
276
|
+
@art = Article.new(:title => "Saving this")
|
277
|
+
@art.save
|
278
|
+
end
|
279
|
+
|
71
280
|
it "should define the updated_at and created_at getters and set the values" do
|
72
281
|
@obj.save
|
73
282
|
obj = WithDefaultValues.get(@obj.id)
|
@@ -76,9 +285,18 @@ describe "ExtendedDocument" do
|
|
76
285
|
obj.updated_at.should be_an_instance_of(Time)
|
77
286
|
obj.created_at.to_s.should == @obj.updated_at.to_s
|
78
287
|
end
|
288
|
+
it "should set the time on create" do
|
289
|
+
(Time.now - @art.created_at).should < 2
|
290
|
+
foundart = Article.get @art.id
|
291
|
+
foundart.created_at.should == foundart.updated_at
|
292
|
+
end
|
293
|
+
it "should set the time on update" do
|
294
|
+
@art.save
|
295
|
+
@art.created_at.should < @art.updated_at
|
296
|
+
end
|
79
297
|
end
|
80
298
|
|
81
|
-
describe "saving and retrieving" do
|
299
|
+
describe "basic saving and retrieving" do
|
82
300
|
it "should work fine" do
|
83
301
|
@obj.name = "should be easily saved and retrieved"
|
84
302
|
@obj.save
|
@@ -96,6 +314,145 @@ describe "ExtendedDocument" do
|
|
96
314
|
end
|
97
315
|
end
|
98
316
|
|
317
|
+
describe "saving a model" do
|
318
|
+
before(:all) do
|
319
|
+
@sobj = Basic.new
|
320
|
+
@sobj.save.should == true
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should save the doc" do
|
324
|
+
doc = Basic.get(@sobj.id)
|
325
|
+
doc['_id'].should == @sobj.id
|
326
|
+
end
|
327
|
+
|
328
|
+
it "should be set for resaving" do
|
329
|
+
rev = @obj.rev
|
330
|
+
@sobj['another-key'] = "some value"
|
331
|
+
@sobj.save
|
332
|
+
@sobj.rev.should_not == rev
|
333
|
+
end
|
334
|
+
|
335
|
+
it "should set the id" do
|
336
|
+
@sobj.id.should be_an_instance_of(String)
|
337
|
+
end
|
338
|
+
|
339
|
+
it "should set the type" do
|
340
|
+
@sobj['couchrest-type'].should == 'Basic'
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "saving a model with a unique_id configured" do
|
345
|
+
before(:each) do
|
346
|
+
@art = Article.new
|
347
|
+
@old = Article.database.get('this-is-the-title') rescue nil
|
348
|
+
Article.database.delete_doc(@old) if @old
|
349
|
+
end
|
350
|
+
|
351
|
+
it "should be a new document" do
|
352
|
+
@art.should be_a_new_document
|
353
|
+
@art.title.should be_nil
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should require the title" do
|
357
|
+
lambda{@art.save}.should raise_error
|
358
|
+
@art.title = 'This is the title'
|
359
|
+
@art.save.should == true
|
360
|
+
end
|
361
|
+
|
362
|
+
it "should not change the slug on update" do
|
363
|
+
@art.title = 'This is the title'
|
364
|
+
@art.save.should == true
|
365
|
+
@art.title = 'new title'
|
366
|
+
@art.save.should == true
|
367
|
+
@art.slug.should == 'this-is-the-title'
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should raise an error when the slug is taken" do
|
371
|
+
@art.title = 'This is the title'
|
372
|
+
@art.save.should == true
|
373
|
+
@art2 = Article.new(:title => 'This is the title!')
|
374
|
+
lambda{@art2.save}.should raise_error
|
375
|
+
end
|
376
|
+
|
377
|
+
it "should set the slug" do
|
378
|
+
@art.title = 'This is the title'
|
379
|
+
@art.save.should == true
|
380
|
+
@art.slug.should == 'this-is-the-title'
|
381
|
+
end
|
382
|
+
|
383
|
+
it "should set the id" do
|
384
|
+
@art.title = 'This is the title'
|
385
|
+
@art.save.should == true
|
386
|
+
@art.id.should == 'this-is-the-title'
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe "saving a model with a unique_id lambda" do
|
391
|
+
before(:each) do
|
392
|
+
@templated = WithTemplateAndUniqueID.new
|
393
|
+
@old = WithTemplateAndUniqueID.get('very-important') rescue nil
|
394
|
+
@old.destroy if @old
|
395
|
+
end
|
396
|
+
|
397
|
+
it "should require the field" do
|
398
|
+
lambda{@templated.save}.should raise_error
|
399
|
+
@templated['important-field'] = 'very-important'
|
400
|
+
@templated.save.should == true
|
401
|
+
end
|
402
|
+
|
403
|
+
it "should save with the id" do
|
404
|
+
@templated['important-field'] = 'very-important'
|
405
|
+
@templated.save.should == true
|
406
|
+
t = WithTemplateAndUniqueID.get('very-important')
|
407
|
+
t.should == @templated
|
408
|
+
end
|
409
|
+
|
410
|
+
it "should not change the id on update" do
|
411
|
+
@templated['important-field'] = 'very-important'
|
412
|
+
@templated.save.should == true
|
413
|
+
@templated['important-field'] = 'not-important'
|
414
|
+
@templated.save.should == true
|
415
|
+
t = WithTemplateAndUniqueID.get('very-important')
|
416
|
+
t.should == @templated
|
417
|
+
end
|
418
|
+
|
419
|
+
it "should raise an error when the id is taken" do
|
420
|
+
@templated['important-field'] = 'very-important'
|
421
|
+
@templated.save.should == true
|
422
|
+
lambda{WithTemplateAndUniqueID.new('important-field' => 'very-important').save}.should raise_error
|
423
|
+
end
|
424
|
+
|
425
|
+
it "should set the id" do
|
426
|
+
@templated['important-field'] = 'very-important'
|
427
|
+
@templated.save.should == true
|
428
|
+
@templated.id.should == 'very-important'
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
describe "destroying an instance" do
|
433
|
+
before(:each) do
|
434
|
+
@dobj = Basic.new
|
435
|
+
@dobj.save.should == true
|
436
|
+
end
|
437
|
+
it "should return true" do
|
438
|
+
result = @dobj.destroy
|
439
|
+
result.should == true
|
440
|
+
end
|
441
|
+
it "should be resavable" do
|
442
|
+
pending "TO FIX" do
|
443
|
+
@dobj.destroy
|
444
|
+
@dobj.rev.should be_nil
|
445
|
+
@dobj.id.should be_nil
|
446
|
+
@dobj.save.should == true
|
447
|
+
end
|
448
|
+
end
|
449
|
+
it "should make it go away" do
|
450
|
+
@dobj.destroy
|
451
|
+
lambda{Basic.get(@dobj.id)}.should raise_error
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
|
99
456
|
describe "callbacks" do
|
100
457
|
|
101
458
|
before(:each) do
|
@@ -103,28 +460,11 @@ describe "ExtendedDocument" do
|
|
103
460
|
end
|
104
461
|
|
105
462
|
describe "save" do
|
106
|
-
it "should not run the before filter before saving if the save failed" do
|
107
|
-
@doc.run_before_save.should be_nil
|
108
|
-
@doc.save.should be_true
|
109
|
-
@doc.run_before_save.should be_true
|
110
|
-
end
|
111
|
-
it "should not run the before filter before saving if the save failed" do
|
112
|
-
@doc.should_receive(:save).and_return(false)
|
113
|
-
@doc.run_before_save.should be_nil
|
114
|
-
@doc.save.should be_false
|
115
|
-
@doc.run_before_save.should be_nil
|
116
|
-
end
|
117
463
|
it "should run the after filter after saving" do
|
118
464
|
@doc.run_after_save.should be_nil
|
119
465
|
@doc.save.should be_true
|
120
466
|
@doc.run_after_save.should be_true
|
121
467
|
end
|
122
|
-
it "should not run the after filter before saving if the save failed" do
|
123
|
-
@doc.should_receive(:save).and_return(false)
|
124
|
-
@doc.run_after_save.should be_nil
|
125
|
-
@doc.save.should be_false
|
126
|
-
@doc.run_after_save.should be_nil
|
127
|
-
end
|
128
468
|
end
|
129
469
|
describe "create" do
|
130
470
|
it "should run the before save filter when creating" do
|
@@ -132,14 +472,6 @@ describe "ExtendedDocument" do
|
|
132
472
|
@doc.create.should_not be_nil
|
133
473
|
@doc.run_before_save.should be_true
|
134
474
|
end
|
135
|
-
it "should not run the before save filter when the object creation fails" do
|
136
|
-
pending "need to ask wycats about chainable callbacks" do
|
137
|
-
@doc.should_receive(:create_without_callbacks).and_return(false)
|
138
|
-
@doc.run_before_save.should be_nil
|
139
|
-
@doc.save
|
140
|
-
@doc.run_before_save.should be_nil
|
141
|
-
end
|
142
|
-
end
|
143
475
|
it "should run the before create filter" do
|
144
476
|
@doc.run_before_create.should be_nil
|
145
477
|
@doc.create.should_not be_nil
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
require File.join(FIXTURE_PATH, 'more', 'article')
|
3
|
+
require File.join(FIXTURE_PATH, 'more', 'course')
|
4
|
+
|
5
|
+
describe "ExtendedDocument views" do
|
6
|
+
|
7
|
+
describe "a model with simple views and a default param" do
|
8
|
+
before(:all) do
|
9
|
+
Article.all.map{|a| a.destroy(true)}
|
10
|
+
Article.database.bulk_delete
|
11
|
+
written_at = Time.now - 24 * 3600 * 7
|
12
|
+
@titles = ["this and that", "also interesting", "more fun", "some junk"]
|
13
|
+
@titles.each do |title|
|
14
|
+
a = Article.new(:title => title)
|
15
|
+
a.date = written_at
|
16
|
+
a.save
|
17
|
+
written_at += 24 * 3600
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should have a design doc" do
|
22
|
+
Article.design_doc["views"]["by_date"].should_not be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should save the design doc" do
|
26
|
+
Article.by_date #rescue nil
|
27
|
+
doc = Article.database.get Article.design_doc.id
|
28
|
+
doc['views']['by_date'].should_not be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return the matching raw view result" do
|
32
|
+
view = Article.by_date :raw => true
|
33
|
+
view['rows'].length.should == 4
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not include non-Articles" do
|
37
|
+
Article.database.save_doc({"date" => 1})
|
38
|
+
view = Article.by_date :raw => true
|
39
|
+
view['rows'].length.should == 4
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return the matching objects (with default argument :descending => true)" do
|
43
|
+
articles = Article.by_date
|
44
|
+
articles.collect{|a|a.title}.should == @titles.reverse
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should allow you to override default args" do
|
48
|
+
articles = Article.by_date :descending => false
|
49
|
+
articles.collect{|a|a.title}.should == @titles
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "another model with a simple view" do
|
54
|
+
before(:all) do
|
55
|
+
reset_test_db!
|
56
|
+
%w{aaa bbb ddd eee}.each do |title|
|
57
|
+
Course.new(:title => title).save
|
58
|
+
end
|
59
|
+
end
|
60
|
+
it "should make the design doc upon first query" do
|
61
|
+
Course.by_title
|
62
|
+
doc = Course.design_doc
|
63
|
+
doc['views']['all']['map'].should include('Course')
|
64
|
+
end
|
65
|
+
it "should can query via view" do
|
66
|
+
# register methods with method-missing, for local dispatch. method
|
67
|
+
# missing lookup table, no heuristics.
|
68
|
+
view = Course.view :by_title
|
69
|
+
designed = Course.by_title
|
70
|
+
view.should == designed
|
71
|
+
end
|
72
|
+
it "should get them" do
|
73
|
+
rs = Course.by_title
|
74
|
+
rs.length.should == 4
|
75
|
+
end
|
76
|
+
it "should yield" do
|
77
|
+
courses = []
|
78
|
+
rs = Course.by_title # remove me
|
79
|
+
Course.view(:by_title) do |course|
|
80
|
+
courses << course
|
81
|
+
end
|
82
|
+
courses[0]["doc"]["title"].should =='aaa'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
describe "a ducktype view" do
|
88
|
+
before(:all) do
|
89
|
+
@id = TEST_SERVER.default_database.save_doc({:dept => true})['id']
|
90
|
+
end
|
91
|
+
it "should setup" do
|
92
|
+
duck = Course.get(@id) # from a different db
|
93
|
+
duck["dept"].should == true
|
94
|
+
end
|
95
|
+
it "should make the design doc" do
|
96
|
+
@as = Course.by_dept
|
97
|
+
@doc = Course.design_doc
|
98
|
+
@doc["views"]["by_dept"]["map"].should_not include("couchrest")
|
99
|
+
end
|
100
|
+
it "should not look for class" do |variable|
|
101
|
+
@as = Course.by_dept
|
102
|
+
@as[0]['_id'].should == @id
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "a model with a compound key view" do
|
107
|
+
before(:all) do
|
108
|
+
written_at = Time.now - 24 * 3600 * 7
|
109
|
+
@titles = ["uniq one", "even more interesting", "less fun", "not junk"]
|
110
|
+
@user_ids = ["quentin", "aaron"]
|
111
|
+
@titles.each_with_index do |title,i|
|
112
|
+
u = i % 2
|
113
|
+
a = Article.new(:title => title, :user_id => @user_ids[u])
|
114
|
+
a.date = written_at
|
115
|
+
a.save
|
116
|
+
written_at += 24 * 3600
|
117
|
+
end
|
118
|
+
end
|
119
|
+
it "should create the design doc" do
|
120
|
+
Article.by_user_id_and_date rescue nil
|
121
|
+
doc = Article.design_doc
|
122
|
+
doc['views']['by_date'].should_not be_nil
|
123
|
+
end
|
124
|
+
it "should sort correctly" do
|
125
|
+
articles = Article.by_user_id_and_date
|
126
|
+
articles.collect{|a|a['user_id']}.should == ['aaron', 'aaron', 'quentin',
|
127
|
+
'quentin']
|
128
|
+
articles[1].title.should == 'not junk'
|
129
|
+
end
|
130
|
+
it "should be queryable with couchrest options" do
|
131
|
+
articles = Article.by_user_id_and_date :limit => 1, :startkey => 'quentin'
|
132
|
+
articles.length.should == 1
|
133
|
+
articles[0].title.should == "even more interesting"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "with a custom view" do
|
138
|
+
before(:all) do
|
139
|
+
@titles = ["very uniq one", "even less interesting", "some fun",
|
140
|
+
"really junk", "crazy bob"]
|
141
|
+
@tags = ["cool", "lame"]
|
142
|
+
@titles.each_with_index do |title,i|
|
143
|
+
u = i % 2
|
144
|
+
a = Article.new(:title => title, :tags => [@tags[u]])
|
145
|
+
a.save
|
146
|
+
end
|
147
|
+
end
|
148
|
+
it "should be available raw" do
|
149
|
+
view = Article.by_tags :raw => true
|
150
|
+
view['rows'].length.should == 5
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should be default to :reduce => false" do
|
154
|
+
ars = Article.by_tags
|
155
|
+
ars.first.tags.first.should == 'cool'
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should be raw when reduce is true" do
|
159
|
+
view = Article.by_tags :reduce => true, :group => true
|
160
|
+
view['rows'].find{|r|r['key'] == 'cool'}['value'].should == 3
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# TODO: moved to Design, delete
|
165
|
+
describe "adding a view" do
|
166
|
+
before(:each) do
|
167
|
+
Article.by_date
|
168
|
+
@design_docs = Article.database.documents :startkey => "_design/",
|
169
|
+
:endkey => "_design/\u9999"
|
170
|
+
end
|
171
|
+
it "should not create a design doc on view definition" do
|
172
|
+
Article.view_by :created_at
|
173
|
+
newdocs = Article.database.documents :startkey => "_design/",
|
174
|
+
:endkey => "_design/\u9999"
|
175
|
+
newdocs["rows"].length.should == @design_docs["rows"].length
|
176
|
+
end
|
177
|
+
it "should create a new design document on view access" do
|
178
|
+
Article.view_by :updated_at
|
179
|
+
Article.by_updated_at
|
180
|
+
newdocs = Article.database.documents :startkey => "_design/",
|
181
|
+
:endkey => "_design/\u9999"
|
182
|
+
# puts @design_docs.inspect
|
183
|
+
# puts newdocs.inspect
|
184
|
+
newdocs["rows"].length.should == @design_docs["rows"].length + 1
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "with a lot of designs left around" do
|
189
|
+
before(:each) do
|
190
|
+
Article.by_date
|
191
|
+
Article.view_by :field
|
192
|
+
Article.by_field
|
193
|
+
end
|
194
|
+
it "should clean them up" do
|
195
|
+
Article.view_by :stream
|
196
|
+
Article.by_stream
|
197
|
+
ddocs = Article.all_design_doc_versions
|
198
|
+
ddocs["rows"].length.should > 1
|
199
|
+
Article.cleanup_design_docs!
|
200
|
+
ddocs = Article.all_design_doc_versions
|
201
|
+
ddocs["rows"].length.should == 1
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
|
2
2
|
require File.join(FIXTURE_PATH, 'more', 'card')
|
3
3
|
require File.join(FIXTURE_PATH, 'more', 'invoice')
|
4
|
-
require File.join(FIXTURE_PATH, 'more', 'service
|
4
|
+
require File.join(FIXTURE_PATH, 'more', 'service')
|
5
|
+
require File.join(FIXTURE_PATH, 'more', 'event')
|
5
6
|
|
6
7
|
|
7
8
|
describe "ExtendedDocument properties" do
|
@@ -43,7 +44,6 @@ describe "ExtendedDocument properties" do
|
|
43
44
|
end
|
44
45
|
|
45
46
|
describe "validation" do
|
46
|
-
|
47
47
|
before(:each) do
|
48
48
|
@invoice = Invoice.new(:client_name => "matt", :employee_name => "Chris", :location => "San Diego, CA")
|
49
49
|
end
|
@@ -79,11 +79,9 @@ describe "ExtendedDocument properties" do
|
|
79
79
|
@invoice.save.should be_false
|
80
80
|
@invoice.should be_new_document
|
81
81
|
end
|
82
|
-
|
83
82
|
end
|
84
83
|
|
85
84
|
describe "autovalidation" do
|
86
|
-
|
87
85
|
before(:each) do
|
88
86
|
@service = Service.new(:name => "Coumpound analysis", :price => 3_000)
|
89
87
|
end
|
@@ -112,7 +110,20 @@ describe "ExtendedDocument properties" do
|
|
112
110
|
@service.errors.on(:name).first.should == "Name must be between 4 and 19 characters long"
|
113
111
|
end
|
114
112
|
end
|
115
|
-
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "casting" do
|
116
|
+
describe "cast keys to any type" do
|
117
|
+
before(:all) do
|
118
|
+
event_doc = { :subject => "Some event", :occurs_at => Time.now }
|
119
|
+
e = Event.database.save_doc event_doc
|
120
|
+
|
121
|
+
@event = Event.get e['id']
|
122
|
+
end
|
123
|
+
it "should cast created_at to Time" do
|
124
|
+
@event['occurs_at'].should be_an_instance_of(Time)
|
125
|
+
end
|
126
|
+
end
|
116
127
|
end
|
117
128
|
|
118
129
|
end
|
data/spec/spec_helper.rb
CHANGED