juozasg-couchrest 0.10.1

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.
Files changed (55) hide show
  1. data/LICENSE +176 -0
  2. data/README.rdoc +67 -0
  3. data/Rakefile +86 -0
  4. data/THANKS +15 -0
  5. data/bin/couchapp +58 -0
  6. data/bin/couchdir +20 -0
  7. data/bin/couchview +48 -0
  8. data/examples/model/example.rb +138 -0
  9. data/examples/word_count/markov +38 -0
  10. data/examples/word_count/views/books/chunked-map.js +3 -0
  11. data/examples/word_count/views/books/united-map.js +1 -0
  12. data/examples/word_count/views/markov/chain-map.js +6 -0
  13. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  14. data/examples/word_count/views/word_count/count-map.js +6 -0
  15. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  16. data/examples/word_count/word_count.rb +67 -0
  17. data/examples/word_count/word_count_query.rb +39 -0
  18. data/lib/couchrest/commands/generate.rb +71 -0
  19. data/lib/couchrest/commands/push.rb +103 -0
  20. data/lib/couchrest/core/database.rb +173 -0
  21. data/lib/couchrest/core/design.rb +89 -0
  22. data/lib/couchrest/core/document.rb +60 -0
  23. data/lib/couchrest/core/model.rb +557 -0
  24. data/lib/couchrest/core/server.rb +51 -0
  25. data/lib/couchrest/core/view.rb +4 -0
  26. data/lib/couchrest/helper/file_manager.rb +317 -0
  27. data/lib/couchrest/helper/pager.rb +103 -0
  28. data/lib/couchrest/helper/streamer.rb +44 -0
  29. data/lib/couchrest/helper/templates/bar.txt +11 -0
  30. data/lib/couchrest/helper/templates/example-map.js +8 -0
  31. data/lib/couchrest/helper/templates/example-reduce.js +10 -0
  32. data/lib/couchrest/helper/templates/index.html +26 -0
  33. data/lib/couchrest/monkeypatches.rb +24 -0
  34. data/lib/couchrest.rb +125 -0
  35. data/spec/couchapp_spec.rb +87 -0
  36. data/spec/couchrest/core/couchrest_spec.rb +191 -0
  37. data/spec/couchrest/core/database_spec.rb +478 -0
  38. data/spec/couchrest/core/design_spec.rb +131 -0
  39. data/spec/couchrest/core/document_spec.rb +96 -0
  40. data/spec/couchrest/core/model_spec.rb +660 -0
  41. data/spec/couchrest/helpers/file_manager_spec.rb +203 -0
  42. data/spec/couchrest/helpers/pager_spec.rb +122 -0
  43. data/spec/couchrest/helpers/streamer_spec.rb +23 -0
  44. data/spec/fixtures/attachments/couchdb.png +0 -0
  45. data/spec/fixtures/attachments/test.html +11 -0
  46. data/spec/fixtures/views/lib.js +3 -0
  47. data/spec/fixtures/views/test_view/lib.js +3 -0
  48. data/spec/fixtures/views/test_view/only-map.js +4 -0
  49. data/spec/fixtures/views/test_view/test-map.js +3 -0
  50. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  51. data/spec/spec.opts +6 -0
  52. data/spec/spec_helper.rb +14 -0
  53. data/utils/remap.rb +27 -0
  54. data/utils/subset.rb +30 -0
  55. metadata +154 -0
@@ -0,0 +1,660 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ class Basic < CouchRest::Model
4
+ end
5
+
6
+ class BasicWithValidation < CouchRest::Model
7
+
8
+ before :save, :validate
9
+ key_accessor :name
10
+
11
+ def validate
12
+ throw(:halt, false) unless name
13
+ end
14
+ end
15
+
16
+ class WithTemplate < CouchRest::Model
17
+ unique_id do |model|
18
+ model['important-field']
19
+ end
20
+ set_default({
21
+ :preset => 'value',
22
+ 'more-template' => [1,2,3]
23
+ })
24
+ key_accessor :preset
25
+ end
26
+
27
+ class Question < CouchRest::Model
28
+ key_accessor :q, :a
29
+ couchrest_type = 'Question'
30
+ end
31
+
32
+ class Person < CouchRest::Model
33
+ key_accessor :name
34
+ def last_name
35
+ name.last
36
+ end
37
+ end
38
+
39
+ class Course < CouchRest::Model
40
+ key_accessor :title
41
+ cast :questions, :as => ['Question']
42
+ cast :professor, :as => 'Person'
43
+ view_by :title
44
+ view_by :dept, :ducktype => true
45
+ end
46
+
47
+ class Article < CouchRest::Model
48
+ use_database CouchRest.database!('http://localhost:5984/couchrest-model-test')
49
+ unique_id :slug
50
+
51
+ view_by :date, :descending => true
52
+ view_by :user_id, :date
53
+
54
+ view_by :tags,
55
+ :map =>
56
+ "function(doc) {
57
+ if (doc['couchrest-type'] == 'Article' && doc.tags) {
58
+ doc.tags.forEach(function(tag){
59
+ emit(tag, 1);
60
+ });
61
+ }
62
+ }",
63
+ :reduce =>
64
+ "function(keys, values, rereduce) {
65
+ return sum(values);
66
+ }"
67
+
68
+ key_writer :date
69
+ key_reader :slug, :created_at, :updated_at
70
+ key_accessor :title, :tags
71
+
72
+ timestamps!
73
+
74
+ before(:create, :generate_slug_from_title)
75
+ def generate_slug_from_title
76
+ self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'')
77
+ end
78
+ end
79
+
80
+ describe CouchRest::Model do
81
+ before(:all) do
82
+ @cr = CouchRest.new(COUCHHOST)
83
+ @db = @cr.database(TESTDB)
84
+ @db.delete! rescue nil
85
+ @db = @cr.create_db(TESTDB) rescue nil
86
+ @adb = @cr.database('couchrest-model-test')
87
+ @adb.delete! rescue nil
88
+ CouchRest.database!('http://localhost:5984/couchrest-model-test')
89
+ CouchRest::Model.default_database = CouchRest.database!('http://localhost:5984/couchrest-test')
90
+ end
91
+
92
+ it "should use the default database" do
93
+ Basic.database.info['db_name'].should == 'couchrest-test'
94
+ end
95
+
96
+ it "should override the default db" do
97
+ Article.database.info['db_name'].should == 'couchrest-model-test'
98
+ end
99
+
100
+ describe "a new model" do
101
+ it "should be a new_record" do
102
+ @obj = Basic.new
103
+ @obj.rev.should be_nil
104
+ @obj.should be_a_new_record
105
+ end
106
+ end
107
+
108
+ describe "a model with key_accessors" do
109
+ it "should allow reading keys" do
110
+ @art = Article.new
111
+ @art['title'] = 'My Article Title'
112
+ @art.title.should == 'My Article Title'
113
+ end
114
+ it "should allow setting keys" do
115
+ @art = Article.new
116
+ @art.title = 'My Article Title'
117
+ @art['title'].should == 'My Article Title'
118
+ end
119
+ end
120
+
121
+ describe "a model with key_writers" do
122
+ it "should allow setting keys" do
123
+ @art = Article.new
124
+ t = Time.now
125
+ @art.date = t
126
+ @art['date'].should == t
127
+ end
128
+ it "should not allow reading keys" do
129
+ @art = Article.new
130
+ t = Time.now
131
+ @art.date = t
132
+ lambda{@art.date}.should raise_error
133
+ end
134
+ end
135
+
136
+ describe "a model with key_readers" do
137
+ it "should allow reading keys" do
138
+ @art = Article.new
139
+ @art['slug'] = 'my-slug'
140
+ @art.slug.should == 'my-slug'
141
+ end
142
+ it "should not allow setting keys" do
143
+ @art = Article.new
144
+ lambda{@art.slug = 'My Article Title'}.should raise_error
145
+ end
146
+ end
147
+
148
+ describe "update attributes without saving" do
149
+ before(:each) do
150
+ a = Article.get "big-bad-danger" rescue nil
151
+ a.destroy if a
152
+ @art = Article.new(:title => "big bad danger")
153
+ @art.save
154
+ end
155
+ it "should work for attribute= methods" do
156
+ @art['title'].should == "big bad danger"
157
+ @art.update_attributes('date' => Time.now, :title => "super danger")
158
+ @art['title'].should == "super danger"
159
+ end
160
+
161
+ it "should flip out if an attribute= method is missing" do
162
+ lambda {
163
+ @art.update_attributes('slug' => "new-slug", :title => "super danger")
164
+ }.should raise_error
165
+ end
166
+
167
+ it "should not change other attributes if there is an error" do
168
+ lambda {
169
+ @art.update_attributes('slug' => "new-slug", :title => "super danger")
170
+ }.should raise_error
171
+ @art['title'].should == "big bad danger"
172
+ end
173
+
174
+ end
175
+
176
+ describe "update attributes" do
177
+ before(:each) do
178
+ a = Article.get "big-bad-danger" rescue nil
179
+ a.destroy if a
180
+ @art = Article.new(:title => "big bad danger")
181
+ @art.save
182
+ end
183
+ it "should save" do
184
+ @art['title'].should == "big bad danger"
185
+ @art.update_attributes('date' => Time.now, :title => "super danger")
186
+ loaded = Article.get @art.id
187
+ loaded['title'].should == "super danger"
188
+ end
189
+ end
190
+
191
+ describe "a model with template values" do
192
+ before(:all) do
193
+ @tmpl = WithTemplate.new
194
+ end
195
+ it "should have fields set when new" do
196
+ @tmpl.preset.should == 'value'
197
+ end
198
+ end
199
+
200
+ describe "getting a model" do
201
+ before(:all) do
202
+ @art = Article.new(:title => 'All About Getting')
203
+ @art.save
204
+ end
205
+ it "should load and instantiate it" do
206
+ foundart = Article.get @art.id
207
+ foundart.title.should == "All About Getting"
208
+ end
209
+ end
210
+
211
+ describe "getting a model with a subobjects array" do
212
+ before(:all) do
213
+ course_doc = {
214
+ "title" => "Metaphysics 200",
215
+ "questions" => [
216
+ {
217
+ "q" => "Carve the ___ of reality at the ___.",
218
+ "a" => ["beast","joints"]
219
+ },{
220
+ "q" => "Who layed the smack down on Leibniz's Law?",
221
+ "a" => "Willard Van Orman Quine"
222
+ }
223
+ ]
224
+ }
225
+ r = Course.database.save course_doc
226
+ @course = Course.get r['id']
227
+ end
228
+ it "should load the course" do
229
+ @course.title.should == "Metaphysics 200"
230
+ end
231
+ it "should instantiate them as such" do
232
+ @course["questions"][0].a[0].should == "beast"
233
+ end
234
+ end
235
+
236
+ describe "finding all instances of a model" do
237
+ before(:all) do
238
+ WithTemplate.new('important-field' => '1').save
239
+ WithTemplate.new('important-field' => '2').save
240
+ WithTemplate.new('important-field' => '3').save
241
+ WithTemplate.new('important-field' => '4').save
242
+ end
243
+ it "should make the design doc" do
244
+ WithTemplate.all
245
+ d = WithTemplate.design_doc
246
+ d['views']['all']['map'].should include('WithTemplate')
247
+ end
248
+ it "should find all" do
249
+ rs = WithTemplate.all
250
+ rs.length.should == 4
251
+ end
252
+ end
253
+
254
+ describe "finding the first instance of a model" do
255
+ before(:all) do
256
+ WithTemplate.new('important-field' => '1').save
257
+ WithTemplate.new('important-field' => '2').save
258
+ WithTemplate.new('important-field' => '3').save
259
+ WithTemplate.new('important-field' => '4').save
260
+ end
261
+ it "should make the design doc" do
262
+ WithTemplate.all
263
+ d = WithTemplate.design_doc
264
+ d['views']['all']['map'].should include('WithTemplate')
265
+ end
266
+ it "should find first" do
267
+ rs = WithTemplate.first
268
+ rs['important-field'].should == "1"
269
+ end
270
+ it "should return nil if no instances are found" do
271
+ WithTemplate.all.each {|obj| obj.destroy }
272
+ WithTemplate.first.should be_nil
273
+ end
274
+ end
275
+
276
+ describe "getting a model with a subobject field" do
277
+ before(:all) do
278
+ course_doc = {
279
+ "title" => "Metaphysics 410",
280
+ "professor" => {
281
+ "name" => ["Mark", "Hinchliff"]
282
+ }
283
+ }
284
+ r = Course.database.save course_doc
285
+ @course = Course.get r['id']
286
+ end
287
+ it "should load the course" do
288
+ @course["professor"]["name"][1].should == "Hinchliff"
289
+ end
290
+ it "should instantiate the professor as a person" do
291
+ @course['professor'].last_name.should == "Hinchliff"
292
+ end
293
+ end
294
+
295
+ describe "saving a model" do
296
+ before(:all) do
297
+ @obj = Basic.new
298
+ @obj.save.should == true
299
+ end
300
+
301
+ it "should save the doc" do
302
+ doc = @obj.database.get @obj.id
303
+ doc['_id'].should == @obj.id
304
+ end
305
+
306
+ it "should be set for resaving" do
307
+ rev = @obj.rev
308
+ @obj['another-key'] = "some value"
309
+ @obj.save
310
+ @obj.rev.should_not == rev
311
+ end
312
+
313
+ it "should set the id" do
314
+ @obj.id.should be_an_instance_of(String)
315
+ end
316
+
317
+ it "should set the type" do
318
+ @obj['couchrest-type'].should == 'Basic'
319
+ end
320
+ end
321
+
322
+ describe "saving a model with validation hooks added as extlib" do
323
+ before(:all) do
324
+ @obj = BasicWithValidation.new
325
+ end
326
+
327
+ it "save should return false is the model doesn't save as expected" do
328
+ @obj.save.should be_false
329
+ end
330
+
331
+ it "save! should raise and exception if the model doesn't save" do
332
+ lambda{ @obj.save!}.should raise_error("#{@obj.inspect} failed to save")
333
+ end
334
+
335
+ end
336
+
337
+ describe "saving a model with a unique_id configured" do
338
+ before(:each) do
339
+ @art = Article.new
340
+ @old = Article.database.get('this-is-the-title') rescue nil
341
+ Article.database.delete(@old) if @old
342
+ end
343
+
344
+ it "should be a new document" do
345
+ @art.should be_a_new_document
346
+ @art.title.should be_nil
347
+ end
348
+
349
+ it "should require the title" do
350
+ lambda{@art.save}.should raise_error
351
+ @art.title = 'This is the title'
352
+ @art.save.should == true
353
+ end
354
+
355
+ it "should not change the slug on update" do
356
+ @art.title = 'This is the title'
357
+ @art.save.should == true
358
+ @art.title = 'new title'
359
+ @art.save.should == true
360
+ @art.slug.should == 'this-is-the-title'
361
+ end
362
+
363
+ it "should raise an error when the slug is taken" do
364
+ @art.title = 'This is the title'
365
+ @art.save.should == true
366
+ @art2 = Article.new(:title => 'This is the title!')
367
+ lambda{@art2.save}.should raise_error
368
+ end
369
+
370
+ it "should set the slug" do
371
+ @art.title = 'This is the title'
372
+ @art.save.should == true
373
+ @art.slug.should == 'this-is-the-title'
374
+ end
375
+
376
+ it "should set the id" do
377
+ @art.title = 'This is the title'
378
+ @art.save.should == true
379
+ @art.id.should == 'this-is-the-title'
380
+ end
381
+ end
382
+
383
+ describe "saving a model with a unique_id lambda" do
384
+ before(:each) do
385
+ @templated = WithTemplate.new
386
+ @old = WithTemplate.get('very-important') rescue nil
387
+ @old.destroy if @old
388
+ end
389
+
390
+ it "should require the field" do
391
+ lambda{@templated.save}.should raise_error
392
+ @templated['important-field'] = 'very-important'
393
+ @templated.save.should == true
394
+ end
395
+
396
+ it "should save with the id" do
397
+ @templated['important-field'] = 'very-important'
398
+ @templated.save.should == true
399
+ t = WithTemplate.get('very-important')
400
+ t.should == @templated
401
+ end
402
+
403
+ it "should not change the id on update" do
404
+ @templated['important-field'] = 'very-important'
405
+ @templated.save.should == true
406
+ @templated['important-field'] = 'not-important'
407
+ @templated.save.should == true
408
+ t = WithTemplate.get('very-important')
409
+ t.should == @templated
410
+ end
411
+
412
+ it "should raise an error when the id is taken" do
413
+ @templated['important-field'] = 'very-important'
414
+ @templated.save.should == true
415
+ lambda{WithTemplate.new('important-field' => 'very-important').save}.should raise_error
416
+ end
417
+
418
+ it "should set the id" do
419
+ @templated['important-field'] = 'very-important'
420
+ @templated.save.should == true
421
+ @templated.id.should == 'very-important'
422
+ end
423
+ end
424
+
425
+ describe "a model with timestamps" do
426
+ before(:each) do
427
+ oldart = Article.get "saving-this" rescue nil
428
+ oldart.destroy if oldart
429
+ @art = Article.new(:title => "Saving this")
430
+ @art.save
431
+ end
432
+ it "should set the time on create" do
433
+ (Time.now - @art.created_at).should < 2
434
+ foundart = Article.get @art.id
435
+ foundart.created_at.should == foundart.updated_at
436
+ end
437
+ it "should set the time on update" do
438
+ @art.save
439
+ @art.created_at.should < @art.updated_at
440
+ end
441
+ end
442
+
443
+ describe "a model with simple views and a default param" do
444
+ before(:all) do
445
+ written_at = Time.now - 24 * 3600 * 7
446
+ @titles = ["this and that", "also interesting", "more fun", "some junk"]
447
+ @titles.each do |title|
448
+ a = Article.new(:title => title)
449
+ a.date = written_at
450
+ a.save
451
+ written_at += 24 * 3600
452
+ end
453
+ end
454
+
455
+ it "should have a design doc" do
456
+ Article.design_doc["views"]["by_date"].should_not be_nil
457
+ end
458
+
459
+ it "should save the design doc" do
460
+ Article.by_date #rescue nil
461
+ doc = Article.database.get Article.design_doc.id
462
+ doc['views']['by_date'].should_not be_nil
463
+ end
464
+
465
+ it "should return the matching raw view result" do
466
+ view = Article.by_date :raw => true
467
+ view['rows'].length.should == 4
468
+ end
469
+
470
+ it "should not include non-Articles" do
471
+ Article.database.save({"date" => 1})
472
+ view = Article.by_date :raw => true
473
+ view['rows'].length.should == 4
474
+ end
475
+
476
+ it "should return the matching objects (with default argument :descending => true)" do
477
+ articles = Article.by_date
478
+ articles.collect{|a|a.title}.should == @titles.reverse
479
+ end
480
+
481
+ it "should allow you to override default args" do
482
+ articles = Article.by_date :descending => false
483
+ articles.collect{|a|a.title}.should == @titles
484
+ end
485
+ end
486
+
487
+ describe "another model with a simple view" do
488
+ before(:all) do
489
+ Course.database.delete! rescue nil
490
+ @db = @cr.create_db(TESTDB) rescue nil
491
+ %w{aaa bbb ddd eee}.each do |title|
492
+ Course.new(:title => title).save
493
+ end
494
+ end
495
+ it "should make the design doc upon first query" do
496
+ Course.by_title
497
+ doc = Course.design_doc
498
+ doc['views']['all']['map'].should include('Course')
499
+ end
500
+ it "should can query via view" do
501
+ # register methods with method-missing, for local dispatch. method
502
+ # missing lookup table, no heuristics.
503
+ view = Course.view :by_title
504
+ designed = Course.by_title
505
+ view.should == designed
506
+ end
507
+ it "should get them" do
508
+ rs = Course.by_title
509
+ rs.length.should == 4
510
+ end
511
+ it "should yield" do
512
+ courses = []
513
+ rs = Course.by_title # remove me
514
+ Course.view(:by_title) do |course|
515
+ courses << course
516
+ end
517
+ courses[0]["doc"]["title"].should =='aaa'
518
+ end
519
+ end
520
+
521
+
522
+ describe "a ducktype view" do
523
+ before(:all) do
524
+ @id = @db.save({:dept => true})['id']
525
+ end
526
+ it "should setup" do
527
+ duck = Course.get(@id) # from a different db
528
+ duck["dept"].should == true
529
+ end
530
+ it "should make the design doc" do
531
+ @as = Course.by_dept
532
+ @doc = Course.design_doc
533
+ @doc["views"]["by_dept"]["map"].should_not include("couchrest")
534
+ end
535
+ it "should not look for class" do |variable|
536
+ @as = Course.by_dept
537
+ @as[0]['_id'].should == @id
538
+ end
539
+ end
540
+
541
+ describe "a model with a compound key view" do
542
+ before(:all) do
543
+ written_at = Time.now - 24 * 3600 * 7
544
+ @titles = ["uniq one", "even more interesting", "less fun", "not junk"]
545
+ @user_ids = ["quentin", "aaron"]
546
+ @titles.each_with_index do |title,i|
547
+ u = i % 2
548
+ a = Article.new(:title => title, :user_id => @user_ids[u])
549
+ a.date = written_at
550
+ a.save
551
+ written_at += 24 * 3600
552
+ end
553
+ end
554
+ it "should create the design doc" do
555
+ Article.by_user_id_and_date rescue nil
556
+ doc = Article.design_doc
557
+ doc['views']['by_date'].should_not be_nil
558
+ end
559
+ it "should sort correctly" do
560
+ articles = Article.by_user_id_and_date
561
+ articles.collect{|a|a['user_id']}.should == ['aaron', 'aaron', 'quentin',
562
+ 'quentin']
563
+ articles[1].title.should == 'not junk'
564
+ end
565
+ it "should be queryable with couchrest options" do
566
+ articles = Article.by_user_id_and_date :count => 1, :startkey => 'quentin'
567
+ articles.length.should == 1
568
+ articles[0].title.should == "even more interesting"
569
+ end
570
+ end
571
+
572
+ describe "with a custom view" do
573
+ before(:all) do
574
+ @titles = ["very uniq one", "even less interesting", "some fun",
575
+ "really junk", "crazy bob"]
576
+ @tags = ["cool", "lame"]
577
+ @titles.each_with_index do |title,i|
578
+ u = i % 2
579
+ a = Article.new(:title => title, :tags => [@tags[u]])
580
+ a.save
581
+ end
582
+ end
583
+ it "should be available raw" do
584
+ view = Article.by_tags :raw => true
585
+ view['rows'].length.should == 5
586
+ end
587
+
588
+ it "should be default to :reduce => false" do
589
+ ars = Article.by_tags
590
+ ars.first.tags.first.should == 'cool'
591
+ end
592
+
593
+ it "should be raw when reduce is true" do
594
+ view = Article.by_tags :reduce => true, :group => true
595
+ view['rows'].find{|r|r['key'] == 'cool'}['value'].should == 3
596
+ end
597
+ end
598
+
599
+ # TODO: moved to Design, delete
600
+ describe "adding a view" do
601
+ before(:each) do
602
+ Article.by_date
603
+ @design_docs = Article.database.documents :startkey => "_design/",
604
+ :endkey => "_design/\u9999"
605
+ end
606
+ it "should not create a design doc on view definition" do
607
+ Article.view_by :created_at
608
+ newdocs = Article.database.documents :startkey => "_design/",
609
+ :endkey => "_design/\u9999"
610
+ newdocs["rows"].length.should == @design_docs["rows"].length
611
+ end
612
+ it "should create a new design document on view access" do
613
+ Article.view_by :updated_at
614
+ Article.by_updated_at
615
+ newdocs = Article.database.documents :startkey => "_design/",
616
+ :endkey => "_design/\u9999"
617
+ # puts @design_docs.inspect
618
+ # puts newdocs.inspect
619
+ newdocs["rows"].length.should == @design_docs["rows"].length + 1
620
+ end
621
+ end
622
+
623
+ describe "with a lot of designs left around" do
624
+ before(:each) do
625
+ Article.by_date
626
+ Article.view_by :field
627
+ Article.by_field
628
+ end
629
+ it "should clean them up" do
630
+ Article.view_by :stream
631
+ Article.by_stream
632
+ ddocs = Article.all_design_doc_versions
633
+ ddocs["rows"].length.should > 1
634
+ Article.cleanup_design_docs!
635
+ ddocs = Article.all_design_doc_versions
636
+ ddocs["rows"].length.should == 1
637
+ end
638
+ end
639
+
640
+ describe "destroying an instance" do
641
+ before(:each) do
642
+ @obj = Basic.new
643
+ @obj.save.should == true
644
+ end
645
+ it "should return true" do
646
+ result = @obj.destroy
647
+ result.should == true
648
+ end
649
+ it "should be resavable" do
650
+ @obj.destroy
651
+ @obj.rev.should be_nil
652
+ @obj.id.should be_nil
653
+ @obj.save.should == true
654
+ end
655
+ it "should make it go away" do
656
+ @obj.destroy
657
+ lambda{Basic.get(@obj.id)}.should raise_error
658
+ end
659
+ end
660
+ end