juozasg-couchrest 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
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