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,478 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe CouchRest::Database do
4
+ before(:each) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ @db = @cr.database(TESTDB)
7
+ @db.delete! rescue nil
8
+ @db = @cr.create_db(TESTDB) rescue nil
9
+ end
10
+
11
+ describe "map query with _temp_view in Javascript" do
12
+ before(:each) do
13
+ @db.bulk_save([
14
+ {"wild" => "and random"},
15
+ {"mild" => "yet local"},
16
+ {"another" => ["set","of","keys"]}
17
+ ])
18
+ @temp_view = {:map => "function(doc){for(var w in doc){ if(!w.match(/^_/))emit(w,doc[w])}}"}
19
+ end
20
+ it "should return the result of the temporary function" do
21
+ rs = @db.temp_view(@temp_view)
22
+ rs['rows'].select{|r|r['key'] == 'wild' && r['value'] == 'and random'}.length.should == 1
23
+ end
24
+ it "should work with a range" do
25
+ rs = @db.temp_view(@temp_view, :startkey => "b", :endkey => "z")
26
+ rs['rows'].length.should == 2
27
+ end
28
+ it "should work with a key" do
29
+ rs = @db.temp_view(@temp_view, :key => "wild")
30
+ rs['rows'].length.should == 1
31
+ end
32
+ it "should work with a count" do
33
+ rs = @db.temp_view(@temp_view, :count => 1)
34
+ rs['rows'].length.should == 1
35
+ end
36
+ it "should work with multi-keys" do
37
+ rs = @db.temp_view(@temp_view, :keys => ["another", "wild"])
38
+ rs['rows'].length.should == 2
39
+ end
40
+ end
41
+
42
+ describe "map/reduce query with _temp_view in Javascript" do
43
+ before(:each) do
44
+ @db.bulk_save([
45
+ {"beverage" => "beer", :count => 4},
46
+ {"beverage" => "beer", :count => 2},
47
+ {"beverage" => "tea", :count => 3}
48
+ ])
49
+ end
50
+ it "should return the result of the temporary function" do
51
+ rs = @db.temp_view(:map => "function(doc){emit(doc.beverage, doc.count)}", :reduce => "function(beverage,counts){return sum(counts)}")
52
+ # rs.should == 'x'
53
+ rs['rows'][0]['value'].should == 9
54
+ end
55
+ end
56
+
57
+ describe "saving a view" do
58
+ before(:each) do
59
+ @view = {'test' => {'map' => 'function(doc) {
60
+ if (doc.word && !/\W/.test(doc.word)) {
61
+ emit(doc.word,null);
62
+ }
63
+ }'}}
64
+ @db.save({
65
+ "_id" => "_design/test",
66
+ :views => @view
67
+ })
68
+ end
69
+ it "should work properly" do
70
+ @db.bulk_save([
71
+ {"word" => "once"},
72
+ {"word" => "and again"}
73
+ ])
74
+ @db.view('test/test')['total_rows'].should == 1
75
+ end
76
+ it "should round trip" do
77
+ @db.get("_design/test")['views'].should == @view
78
+ end
79
+ end
80
+
81
+ describe "select from an existing view" do
82
+ before(:each) do
83
+ r = @db.save({
84
+ "_id" => "_design/first",
85
+ :views => {
86
+ :test => {
87
+ :map => "function(doc){for(var w in doc){ if(!w.match(/^_/))emit(w,doc[w])}}"
88
+ }
89
+ }
90
+ })
91
+ @db.bulk_save([
92
+ {"wild" => "and random"},
93
+ {"mild" => "yet local"},
94
+ {"another" => ["set","of","keys"]}
95
+ ])
96
+ end
97
+ it "should have the view" do
98
+ @db.get('_design/first')['views']['test']['map'].should include("for(var w in doc)")
99
+ end
100
+ it "should list from the view" do
101
+ rs = @db.view('first/test')
102
+ rs['rows'].select{|r|r['key'] == 'wild' && r['value'] == 'and random'}.length.should == 1
103
+ end
104
+ it "should work with a range" do
105
+ rs = @db.view('first/test', :startkey => "b", :endkey => "z")
106
+ rs['rows'].length.should == 2
107
+ end
108
+ it "should work with a key" do
109
+ rs = @db.view('first/test', :key => "wild")
110
+ rs['rows'].length.should == 1
111
+ end
112
+ it "should work with a count" do
113
+ rs = @db.view('first/test', :count => 1)
114
+ rs['rows'].length.should == 1
115
+ end
116
+ it "should work with multi-keys" do
117
+ rs = @db.view('first/test', :keys => ["another", "wild"])
118
+ rs['rows'].length.should == 2
119
+ end
120
+ it "should accept a block" do
121
+ rows = []
122
+ rs = @db.view('first/test', :include_docs => true) do |row|
123
+ rows << row
124
+ end
125
+ rows.length.should == 4
126
+ rs["total_rows"].should == 3
127
+ end
128
+ end
129
+
130
+ describe "GET (document by id) when the doc exists" do
131
+ before(:each) do
132
+ @r = @db.save({'lemons' => 'from texas', 'and' => 'spain'})
133
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
134
+ @db.save({'_id' => @docid, 'will-exist' => 'here'})
135
+ end
136
+ it "should get the document" do
137
+ doc = @db.get(@r['id'])
138
+ doc['lemons'].should == 'from texas'
139
+ end
140
+ it "should work with a funky id" do
141
+ @db.get(@docid)['will-exist'].should == 'here'
142
+ end
143
+ end
144
+
145
+ describe "POST (adding bulk documents)" do
146
+ it "should add them without ids" do
147
+ rs = @db.bulk_save([
148
+ {"wild" => "and random"},
149
+ {"mild" => "yet local"},
150
+ {"another" => ["set","of","keys"]}
151
+ ])
152
+ rs['new_revs'].each do |r|
153
+ @db.get(r['id'])
154
+ end
155
+ end
156
+
157
+ it "should use uuids when ids aren't provided" do
158
+ @db.server.stub!(:next_uuid).and_return('asdf6sgadkfhgsdfusdf')
159
+
160
+ docs = [{'key' => 'value'}, {'_id' => 'totally-uniq'}]
161
+ id_docs = [{'key' => 'value', '_id' => 'asdf6sgadkfhgsdfusdf'}, {'_id' => 'totally-uniq'}]
162
+ CouchRest.should_receive(:post).with("http://localhost:5984/couchrest-test/_bulk_docs", {:docs => id_docs})
163
+
164
+ @db.bulk_save(docs)
165
+ end
166
+
167
+ it "should add them with uniq ids" do
168
+ rs = @db.bulk_save([
169
+ {"_id" => "oneB", "wild" => "and random"},
170
+ {"_id" => "twoB", "mild" => "yet local"},
171
+ {"another" => ["set","of","keys"]}
172
+ ])
173
+ rs['new_revs'].each do |r|
174
+ @db.get(r['id'])
175
+ end
176
+ end
177
+
178
+ it "in the case of an id conflict should not insert anything" do
179
+ @r = @db.save({'lemons' => 'from texas', 'and' => 'how', "_id" => "oneB"})
180
+
181
+ lambda do
182
+ rs = @db.bulk_save([
183
+ {"_id" => "oneB", "wild" => "and random"},
184
+ {"_id" => "twoB", "mild" => "yet local"},
185
+ {"another" => ["set","of","keys"]}
186
+ ])
187
+ end.should raise_error(RestClient::RequestFailed)
188
+
189
+ lambda do
190
+ @db.get('twoB')
191
+ end.should raise_error(RestClient::ResourceNotFound)
192
+ end
193
+ it "should raise an error that is useful for recovery" do
194
+ @r = @db.save({"_id" => "taken", "field" => "stuff"})
195
+ begin
196
+ rs = @db.bulk_save([
197
+ {"_id" => "taken", "wild" => "and random"},
198
+ {"_id" => "free", "mild" => "yet local"},
199
+ {"another" => ["set","of","keys"]}
200
+ ])
201
+ rescue RestClient::RequestFailed => e
202
+ # soon CouchDB will provide _which_ docs conflicted
203
+ JSON.parse(e.response.body)['error'].should == 'conflict'
204
+ end
205
+ end
206
+ end
207
+
208
+ describe "new document without an id" do
209
+ it "should start empty" do
210
+ @db.documents["total_rows"].should == 0
211
+ end
212
+ it "should create the document and return the id" do
213
+ r = @db.save({'lemons' => 'from texas', 'and' => 'spain'})
214
+ r2 = @db.get(r['id'])
215
+ r2["lemons"].should == "from texas"
216
+ end
217
+ it "should use PUT with UUIDs" do
218
+ CouchRest.should_receive(:put).and_return({"ok" => true, "id" => "100", "rev" => "55"})
219
+ r = @db.save({'just' => ['another document']})
220
+ end
221
+
222
+ end
223
+
224
+ describe "PUT attachment from file" do
225
+ before(:each) do
226
+ filename = FIXTURE_PATH + '/attachments/couchdb.png'
227
+ @file = File.open(filename)
228
+ end
229
+ after(:each) do
230
+ @file.close
231
+ end
232
+ it "should save the attachment to a new doc" do
233
+ r = @db.put_attachment({'_id' => 'attach-this'}, 'couchdb.png', image = @file.read, {:content_type => 'image/png'})
234
+ r['ok'].should == true
235
+ attachment = @db.fetch_attachment("attach-this","couchdb.png")
236
+ attachment.should == image
237
+ end
238
+ end
239
+
240
+ describe "PUT document with attachment" do
241
+ before(:each) do
242
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
243
+ @doc = {
244
+ "_id" => "mydocwithattachment",
245
+ "field" => ["some value"],
246
+ "_attachments" => {
247
+ "test.html" => {
248
+ "type" => "text/html",
249
+ "data" => @attach
250
+ }
251
+ }
252
+ }
253
+ @db.save(@doc)
254
+ end
255
+ it "should save and be indicated" do
256
+ doc = @db.get("mydocwithattachment")
257
+ doc['_attachments']['test.html']['length'].should == @attach.length
258
+ end
259
+ it "should be there" do
260
+ attachment = @db.fetch_attachment("mydocwithattachment","test.html")
261
+ attachment.should == @attach
262
+ end
263
+ end
264
+
265
+ describe "PUT document with attachment stub" do
266
+ before(:each) do
267
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
268
+ doc = {
269
+ '_id' => 'mydocwithattachment',
270
+ 'field' => ['some_value'],
271
+ '_attachments' => {
272
+ 'test.html' => {
273
+ 'type' => 'text/html', 'data' => @attach
274
+ }
275
+ }
276
+ }
277
+ @db.save(doc)
278
+ doc = @db.get('mydocwithattachment')
279
+ doc['field'] << 'another value'
280
+ @db.save(doc)
281
+ end
282
+
283
+ it 'should be there' do
284
+ attachment = @db.fetch_attachment('mydocwithattachment', 'test.html')
285
+ attachment.should == @attach
286
+ end
287
+ end
288
+
289
+ describe "PUT document with multiple attachments" do
290
+ before(:each) do
291
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
292
+ @attach2 = "<html><head><title>Other Doc</title></head><body><p>Has more words.</p></body></html>"
293
+ @doc = {
294
+ "_id" => "mydocwithattachment",
295
+ "field" => ["some value"],
296
+ "_attachments" => {
297
+ "test.html" => {
298
+ "type" => "text/html",
299
+ "data" => @attach
300
+ },
301
+ "other.html" => {
302
+ "type" => "text/html",
303
+ "data" => @attach2
304
+ }
305
+ }
306
+ }
307
+ @db.save(@doc)
308
+ end
309
+ it "should save and be indicated" do
310
+ doc = @db.get("mydocwithattachment")
311
+ doc['_attachments']['test.html']['length'].should == @attach.length
312
+ doc['_attachments']['other.html']['length'].should == @attach2.length
313
+ end
314
+ it "should be there" do
315
+ attachment = @db.fetch_attachment("mydocwithattachment","test.html")
316
+ attachment.should == @attach
317
+ end
318
+ it "should be there" do
319
+ attachment = @db.fetch_attachment("mydocwithattachment","other.html")
320
+ attachment.should == @attach2
321
+ end
322
+ end
323
+
324
+ describe "POST document with attachment (with funky name)" do
325
+ before(:each) do
326
+ @attach = "<html><head><title>My Funky Doc</title></head><body><p>Has words.</p></body></html>"
327
+ @doc = {
328
+ "field" => ["some other value"],
329
+ "_attachments" => {
330
+ "http://example.com/stuff.cgi?things=and%20stuff" => {
331
+ "type" => "text/html",
332
+ "data" => @attach
333
+ }
334
+ }
335
+ }
336
+ @docid = @db.save(@doc)['id']
337
+ end
338
+ it "should save and be indicated" do
339
+ doc = @db.get(@docid)
340
+ doc['_attachments']['http://example.com/stuff.cgi?things=and%20stuff']['length'].should == @attach.length
341
+ end
342
+ it "should be there" do
343
+ attachment = @db.fetch_attachment(@docid,"http://example.com/stuff.cgi?things=and%20stuff")
344
+ attachment.should == @attach
345
+ end
346
+ end
347
+
348
+ describe "PUT (new document with url id)" do
349
+ it "should create the document" do
350
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
351
+ @db.save({'_id' => @docid, 'will-exist' => 'here'})
352
+ lambda{@db.save({'_id' => @docid})}.should raise_error(RestClient::Request::RequestFailed)
353
+ @db.get(@docid)['will-exist'].should == 'here'
354
+ end
355
+ end
356
+
357
+ describe "PUT (new document with id)" do
358
+ it "should start without the document" do
359
+ # r = @db.save({'lemons' => 'from texas', 'and' => 'spain'})
360
+ @db.documents['rows'].each do |doc|
361
+ doc['id'].should_not == 'my-doc'
362
+ end
363
+ # should_not include({'_id' => 'my-doc'})
364
+ # this needs to be a loop over docs on content with the post
365
+ # or instead make it return something with a fancy <=> method
366
+ end
367
+ it "should create the document" do
368
+ @db.save({'_id' => 'my-doc', 'will-exist' => 'here'})
369
+ lambda{@db.save({'_id' => 'my-doc'})}.should raise_error(RestClient::Request::RequestFailed)
370
+ end
371
+ end
372
+
373
+ describe "PUT (existing document with rev)" do
374
+ before(:each) do
375
+ @db.save({'_id' => 'my-doc', 'will-exist' => 'here'})
376
+ @doc = @db.get('my-doc')
377
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
378
+ @db.save({'_id' => @docid, 'now' => 'save'})
379
+ end
380
+ it "should start with the document" do
381
+ @doc['will-exist'].should == 'here'
382
+ @db.get(@docid)['now'].should == 'save'
383
+ end
384
+ it "should save with url id" do
385
+ doc = @db.get(@docid)
386
+ doc['yaml'] = ['json', 'word.']
387
+ @db.save doc
388
+ @db.get(@docid)['yaml'].should == ['json', 'word.']
389
+ end
390
+ it "should fail to resave without the rev" do
391
+ @doc['them-keys'] = 'huge'
392
+ @doc['_rev'] = 'wrong'
393
+ # @db.save(@doc)
394
+ lambda {@db.save(@doc)}.should raise_error
395
+ end
396
+ it "should update the document" do
397
+ @doc['them-keys'] = 'huge'
398
+ @db.save(@doc)
399
+ now = @db.get('my-doc')
400
+ now['them-keys'].should == 'huge'
401
+ end
402
+ end
403
+
404
+ describe "DELETE existing document" do
405
+ before(:each) do
406
+ @r = @db.save({'lemons' => 'from texas', 'and' => 'spain'})
407
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
408
+ @db.save({'_id' => @docid, 'will-exist' => 'here'})
409
+ end
410
+ it "should work" do
411
+ doc = @db.get(@r['id'])
412
+ doc['and'].should == 'spain'
413
+ @db.delete doc
414
+ lambda{@db.get @r['id']}.should raise_error
415
+ end
416
+ it "should work with uri id" do
417
+ doc = @db.get(@docid)
418
+ @db.delete doc
419
+ lambda{@db.get @docid}.should raise_error
420
+ end
421
+ it "should fail without an _id" do
422
+ lambda{@db.delete({"not"=>"a real doc"})}.should raise_error(ArgumentError)
423
+ end
424
+ end
425
+
426
+ it "should list documents" do
427
+ 5.times do
428
+ @db.save({'another' => 'doc', 'will-exist' => 'anywhere'})
429
+ end
430
+ ds = @db.documents
431
+ ds['rows'].should be_an_instance_of(Array)
432
+ ds['rows'][0]['id'].should_not be_nil
433
+ ds['total_rows'].should == 5
434
+ end
435
+
436
+ describe "documents / _all_docs" do
437
+ before(:each) do
438
+ 9.times do |i|
439
+ @db.save({'_id' => "doc#{i}",'another' => 'doc', 'will-exist' => 'here'})
440
+ end
441
+ end
442
+ it "should list documents with keys and such" do
443
+ ds = @db.documents
444
+ ds['rows'].should be_an_instance_of(Array)
445
+ ds['rows'][0]['id'].should == "doc0"
446
+ ds['total_rows'].should == 9
447
+ end
448
+ it "should take query params" do
449
+ ds = @db.documents(:startkey => 'doc0', :endkey => 'doc3')
450
+ ds['rows'].length.should == 4
451
+ ds = @db.documents(:key => 'doc0')
452
+ ds['rows'].length.should == 1
453
+ end
454
+ it "should work with multi-key" do
455
+ rs = @db.documents :keys => ["doc0", "doc7"]
456
+ rs['rows'].length.should == 2
457
+ end
458
+ it "should work with include_docs" do
459
+ ds = @db.documents(:startkey => 'doc0', :endkey => 'doc3', :include_docs => true)
460
+ ds['rows'][0]['doc']['another'].should == "doc"
461
+ end
462
+ end
463
+
464
+ describe "deleting a database" do
465
+ it "should start with the test database" do
466
+ @cr.databases.should include('couchrest-test')
467
+ end
468
+ it "should delete the database" do
469
+ db = @cr.database('couchrest-test')
470
+ # r =
471
+ db.delete!
472
+ # r['ok'].should == true
473
+ @cr.databases.should_not include('couchrest-test')
474
+ end
475
+ end
476
+
477
+
478
+ end
@@ -0,0 +1,131 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe CouchRest::Design do
4
+
5
+ describe "defining a view" do
6
+ it "should add a view to the design doc" do
7
+ @des = CouchRest::Design.new
8
+ method = @des.view_by :name
9
+ method.should == "by_name"
10
+ @des["views"]["by_name"].should_not be_nil
11
+ end
12
+ end
13
+
14
+ describe "with an unsaved view" do
15
+ before(:each) do
16
+ @des = CouchRest::Design.new
17
+ method = @des.view_by :name
18
+ end
19
+ it "should accept a name" do
20
+ @des.name = "mytest"
21
+ @des.name.should == "mytest"
22
+ end
23
+ it "should not save on view definition" do
24
+ @des.rev.should be_nil
25
+ end
26
+ it "should freak out on view access" do
27
+ lambda{@des.view :by_name}.should raise_error
28
+ end
29
+ end
30
+
31
+ describe "saving" do
32
+ before(:each) do
33
+ @des = CouchRest::Design.new
34
+ method = @des.view_by :name
35
+ @des.database = reset_test_db!
36
+ end
37
+ it "should fail without a name" do
38
+ lambda{@des.save}.should raise_error(ArgumentError)
39
+ end
40
+ it "should work with a name" do
41
+ @des.name = "myview"
42
+ @des.save
43
+ end
44
+ end
45
+
46
+ describe "when it's saved" do
47
+ before(:each) do
48
+ @db = reset_test_db!
49
+ @db.bulk_save([{"name" => "x"},{"name" => "y"}])
50
+ @des = CouchRest::Design.new
51
+ @des.database = @db
52
+ method = @des.view_by :name
53
+ end
54
+ it "should by queryable when it's saved" do
55
+ @des.name = "mydesign"
56
+ @des.save
57
+ res = @des.view :by_name
58
+ res["rows"][0]["key"].should == "x"
59
+ end
60
+ end
61
+
62
+ describe "from a saved document" do
63
+ before(:each) do
64
+ @db = reset_test_db!
65
+ @db.save({
66
+ "_id" => "_design/test",
67
+ "views" => {
68
+ "by_name" => {
69
+ "map" => "function(doc){if (doc.name) emit(doc.name, null)}"
70
+ }
71
+ }
72
+ })
73
+ @db.bulk_save([{"name" => "a"},{"name" => "b"}])
74
+ @des = @db.get "_design/test"
75
+ end
76
+ it "should be a Design" do
77
+ @des.should be_an_instance_of CouchRest::Design
78
+ end
79
+ it "should have a modifiable name" do
80
+ @des.name.should == "test"
81
+ @des.name = "supertest"
82
+ @des.id.should == "_design/supertest"
83
+ end
84
+ it "should by queryable" do
85
+ res = @des.view :by_name
86
+ res["rows"][0]["key"].should == "a"
87
+ end
88
+ end
89
+
90
+ describe "a view with default options" do
91
+ before(:all) do
92
+ @db = reset_test_db!
93
+ @des = CouchRest::Design.new
94
+ @des.name = "test"
95
+ method = @des.view_by :name, :descending => true
96
+ @des.database = @db
97
+ @des.save
98
+ @db.bulk_save([{"name" => "a"},{"name" => "z"}])
99
+ end
100
+ it "should save them" do
101
+ @d2 = @db.get(@des.id)
102
+ @d2["views"]["by_name"]["couchrest-defaults"].should == {"descending"=>true}
103
+ end
104
+ it "should use them" do
105
+ res = @des.view :by_name
106
+ res["rows"].first["key"].should == "z"
107
+ end
108
+ it "should override them" do
109
+ res = @des.view :by_name, :descending => false
110
+ res["rows"].first["key"].should == "a"
111
+ end
112
+ end
113
+
114
+ describe "a view with multiple keys" do
115
+ before(:all) do
116
+ @db = reset_test_db!
117
+ @des = CouchRest::Design.new
118
+ @des.name = "test"
119
+ method = @des.view_by :name, :age
120
+ @des.database = @db
121
+ @des.save
122
+ @db.bulk_save([{"name" => "a", "age" => 2},
123
+ {"name" => "a", "age" => 4},{"name" => "z", "age" => 9}])
124
+ end
125
+ it "should work" do
126
+ res = @des.view :by_name_and_age
127
+ res["rows"].first["key"].should == ["a",2]
128
+ end
129
+ end
130
+
131
+ end