sr-couchy 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.textile +77 -0
  2. data/Rakefile +46 -0
  3. data/bin/couchy +80 -0
  4. data/couchy.gemspec +58 -0
  5. data/lib/couchy.rb +21 -0
  6. data/lib/couchy/database.rb +129 -0
  7. data/lib/couchy/server.rb +89 -0
  8. data/spec/couchy_spec.rb +71 -0
  9. data/spec/database_spec.rb +417 -0
  10. data/spec/fixtures/attachments/test.html +11 -0
  11. data/spec/fixtures/views/lib.js +3 -0
  12. data/spec/fixtures/views/test_view/lib.js +3 -0
  13. data/spec/fixtures/views/test_view/only-map.js +4 -0
  14. data/spec/fixtures/views/test_view/test-map.js +3 -0
  15. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  16. data/spec/spec.opts +6 -0
  17. data/spec/spec_helper.rb +5 -0
  18. data/test/couchy_test.rb +13 -0
  19. data/test/database_test.rb +193 -0
  20. data/test/server_test.rb +211 -0
  21. data/test/test_helper.rb +10 -0
  22. data/vendor/addressable/.gitignore +7 -0
  23. data/vendor/addressable/CHANGELOG +51 -0
  24. data/vendor/addressable/LICENSE +20 -0
  25. data/vendor/addressable/README +24 -0
  26. data/vendor/addressable/Rakefile +51 -0
  27. data/vendor/addressable/lib/addressable/idna.rb +4867 -0
  28. data/vendor/addressable/lib/addressable/uri.rb +2212 -0
  29. data/vendor/addressable/lib/addressable/version.rb +35 -0
  30. data/vendor/addressable/spec/addressable/idna_spec.rb +196 -0
  31. data/vendor/addressable/spec/addressable/uri_spec.rb +3827 -0
  32. data/vendor/addressable/spec/data/rfc3986.txt +3419 -0
  33. data/vendor/addressable/tasks/clobber.rake +2 -0
  34. data/vendor/addressable/tasks/gem.rake +62 -0
  35. data/vendor/addressable/tasks/git.rake +40 -0
  36. data/vendor/addressable/tasks/metrics.rake +22 -0
  37. data/vendor/addressable/tasks/rdoc.rake +29 -0
  38. data/vendor/addressable/tasks/rubyforge.rake +89 -0
  39. data/vendor/addressable/tasks/spec.rake +107 -0
  40. data/vendor/addressable/website/index.html +107 -0
  41. metadata +113 -0
@@ -0,0 +1,71 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require File.dirname(__FILE__) + '/../lib/couchy'
3
+
4
+ describe Couchy do
5
+ before(:each) do
6
+ @couch_rest = Couchy.new(CouchHost)
7
+ @database = @couch_rest.database(TestDatabase)
8
+ end
9
+
10
+ after(:each) do
11
+ begin
12
+ @database.delete!
13
+ rescue RestClient::ResourceNotFound
14
+ nil
15
+ end
16
+ end
17
+
18
+ describe 'Getting info' do
19
+ it 'list databases' do
20
+ @couch_rest.databases.should be_an_instance_of(Array)
21
+ end
22
+
23
+ it 'should get info' do
24
+ @couch_rest.info.should have_key('couchdb')
25
+ @couch_rest.info.should have_key('version')
26
+ end
27
+ end
28
+
29
+ it 'should restart' do
30
+ @couch_rest.restart!
31
+ end
32
+
33
+ describe 'initializing a database' do
34
+ it 'should return a database' do
35
+ db = @couch_rest.database(TestDatabase)
36
+ db.should be_an_instance_of(Couchy::Database)
37
+ end
38
+ end
39
+
40
+ describe 'successfully creating a database' do
41
+ it 'should start without a database' do
42
+ @couch_rest.databases.should_not include(TestDatabase)
43
+ end
44
+
45
+ it 'should return the created database' do
46
+ db = @couch_rest.create_db(TestDatabase)
47
+ db.should be_an_instance_of(Couchy::Database)
48
+ end
49
+
50
+ it 'should create the database' do
51
+ db = @couch_rest.create_db(TestDatabase)
52
+ @couch_rest.databases.should include(TestDatabase)
53
+ end
54
+ end
55
+
56
+ describe 'failing to create a database because the name is taken' do
57
+ before(:each) do
58
+ @couch_rest.create_db(TestDatabase)
59
+ end
60
+
61
+ it 'should start with the test database' do
62
+ @couch_rest.databases.should include(TestDatabase)
63
+ end
64
+
65
+ it 'should PUT the database and raise an error' do
66
+ lambda do
67
+ @couch_rest.create_db(TestDatabase)
68
+ end.should raise_error(RestClient::Request::RequestFailed)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,417 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require File.dirname(__FILE__) + '/../lib/couchy'
3
+
4
+ describe Couchy::Database do
5
+ before(:each) do
6
+ @couch_rest = Couchy.new(CouchHost)
7
+ @database = @couch_rest.database(TestDatabase).delete! rescue nil
8
+ @database = @couch_rest.create_db(TestDatabase)
9
+ end
10
+
11
+ describe "map query with _temp_view in Javascript" do
12
+ before(:each) do
13
+ @database.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
+
21
+ it "should return the result of the temporary function" do
22
+ rs = @database.temp_view(@temp_view)
23
+ rs['rows'].select{|r|r['key'] == 'wild' && r['value'] == 'and random'}.length.should == 1
24
+ end
25
+
26
+ it "should work with a range" do
27
+ rs = @database.temp_view(@temp_view,{:startkey => "b", :endkey => "z"})
28
+ rs['rows'].length.should == 2
29
+ end
30
+
31
+ it "should work with a key" do
32
+ rs = @database.temp_view(@temp_view,{:key => "wild"})
33
+ rs['rows'].length.should == 1
34
+ end
35
+
36
+ it "should work with a count" do
37
+ rs = @database.temp_view(@temp_view,{:count => 1})
38
+ rs['rows'].length.should == 1
39
+ end
40
+ end
41
+
42
+ describe "map/reduce query with _temp_view in Javascript" do
43
+ before(:each) do
44
+ @database.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 = @database.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
+ @database.save({
65
+ "_id" => "_design/test",
66
+ :views => @view
67
+ })
68
+ end
69
+ it "should work properly" do
70
+ @database.bulk_save([
71
+ {"word" => "once"},
72
+ {"word" => "and again"}
73
+ ])
74
+ @database.view('test/test')['total_rows'].should == 1
75
+ end
76
+ it "should round trip" do
77
+ @database.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 = @database.save({
84
+ "_id" => "_design/first",
85
+ :views => {
86
+ :test => {
87
+ :map => <<-eoj
88
+ function(doc) {
89
+ for(var w in doc) {
90
+ if(!w.match(/^_/))
91
+ emit(w,doc[w])
92
+ }
93
+ }
94
+ eoj
95
+ }
96
+ }
97
+ })
98
+ @database.bulk_save([
99
+ {"wild" => "and random"},
100
+ {"mild" => "yet local"},
101
+ {"another" => ["set","of","keys"]}
102
+ ])
103
+ end
104
+ it "should have the view" do
105
+ @database.get('_design/first')['views']['test']['map'].should include("for(var w in doc)")
106
+ end
107
+ it "should list from the view" do
108
+ rs = @database.view('first/test')
109
+ rs['rows'].select{|r|r['key'] == 'wild' && r['value'] == 'and random'}.length.should == 1
110
+ end
111
+ it "should work with a range" do
112
+ rs = @database.view('first/test',{:startkey => "b", :endkey => "z"})
113
+ rs['rows'].length.should == 2
114
+ end
115
+ it "should work with a key" do
116
+ rs = @database.view('first/test',{:key => "wild"})
117
+ rs['rows'].length.should == 1
118
+ end
119
+ it "should work with a count" do
120
+ rs = @database.view('first/test',{:count => 1})
121
+ rs['rows'].length.should == 1
122
+ end
123
+ end
124
+
125
+ describe "GET (document by id) when the doc exists" do
126
+ before(:each) do
127
+ @r = @database.save({'lemons' => 'from texas', 'and' => 'spain'})
128
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
129
+ @database.save({'_id' => @docid, 'will-exist' => 'here'})
130
+ end
131
+ it "should get the document" do
132
+ doc = @database.get(@r['id'])
133
+ doc['lemons'].should == 'from texas'
134
+ end
135
+ it "should work with a funky id" do
136
+ @database.get(@docid)['will-exist'].should == 'here'
137
+ end
138
+ end
139
+
140
+ describe "POST (adding bulk documents)" do
141
+ it "should add them without ids" do
142
+ rs = @database.bulk_save([
143
+ {"wild" => "and random"},
144
+ {"mild" => "yet local"},
145
+ {"another" => ["set","of","keys"]}
146
+ ])
147
+ rs['new_revs'].each do |r|
148
+ @database.get(r['id'])
149
+ end
150
+ end
151
+ it "should add them with uniq ids" do
152
+ rs = @database.bulk_save([
153
+ {"_id" => "oneB", "wild" => "and random"},
154
+ {"_id" => "twoB", "mild" => "yet local"},
155
+ {"another" => ["set","of","keys"]}
156
+ ])
157
+ rs['new_revs'].each do |r|
158
+ @database.get(r['id'])
159
+ end
160
+ end
161
+ it "in the case of an id conflict should not insert anything" do
162
+ @r = @database.save({'lemons' => 'from texas', 'and' => 'how', "_id" => "oneB"})
163
+
164
+ lambda do
165
+ rs = @database.bulk_save([
166
+ {"_id" => "oneB", "wild" => "and random"},
167
+ {"_id" => "twoB", "mild" => "yet local"},
168
+ {"another" => ["set","of","keys"]}
169
+ ])
170
+ end.should raise_error(RestClient::RequestFailed)
171
+
172
+ lambda do
173
+ @database.get('twoB')
174
+ end.should raise_error(RestClient::ResourceNotFound)
175
+ end
176
+ end
177
+
178
+ describe "POST (new document without an id)" do
179
+ it "should start empty" do
180
+ @database.documents["total_rows"].should == 0
181
+ end
182
+ it "should create the document and return the id" do
183
+ r = @database.save({'lemons' => 'from texas', 'and' => 'spain'})
184
+ r2 = @database.get(r['id'])
185
+ r2["lemons"].should == "from texas"
186
+ end
187
+ end
188
+
189
+ describe "PUT document with attachment" do
190
+ before(:each) do
191
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
192
+ @doc = {
193
+ "_id" => "mydocwithattachment",
194
+ "field" => ["some value"],
195
+ "_attachments" => {
196
+ "test.html" => {
197
+ "type" => "text/html",
198
+ "data" => @attach
199
+ }
200
+ }
201
+ }
202
+ @database.save(@doc)
203
+ end
204
+ it "should save and be indicated" do
205
+ doc = @database.get("mydocwithattachment")
206
+ doc['_attachments']['test.html']['length'].should == @attach.length
207
+ end
208
+ it "should be there" do
209
+ attachment = @database.fetch_attachment("mydocwithattachment","test.html")
210
+ attachment.should == @attach
211
+ end
212
+ end
213
+
214
+ describe "PUT document with attachment stub" do
215
+ before(:each) do
216
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
217
+ doc = {
218
+ '_id' => 'mydocwithattachment',
219
+ 'field' => ['some_value'],
220
+ '_attachments' => {
221
+ 'test.html' => {
222
+ 'type' => 'text/html', 'data' => @attach
223
+ }
224
+ }
225
+ }
226
+ @database.save(doc)
227
+ doc = @database.get('mydocwithattachment')
228
+ doc['field'] << 'another value'
229
+ @database.save(doc)
230
+ end
231
+
232
+ it 'should be there' do
233
+ attachment = @database.fetch_attachment('mydocwithattachment', 'test.html')
234
+ attachment.should == @attach
235
+ end
236
+ end
237
+
238
+
239
+ describe "PUT document with multiple attachments" do
240
+ before(:each) do
241
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
242
+ @attach2 = "<html><head><title>Other Doc</title></head><body><p>Has more 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
+ "other.html" => {
252
+ "type" => "text/html",
253
+ "data" => @attach2
254
+ }
255
+ }
256
+ }
257
+ @database.save(@doc)
258
+ end
259
+ it "should save and be indicated" do
260
+ doc = @database.get("mydocwithattachment")
261
+ doc['_attachments']['test.html']['length'].should == @attach.length
262
+ doc['_attachments']['other.html']['length'].should == @attach2.length
263
+ end
264
+ it "should be there" do
265
+ attachment = @database.fetch_attachment("mydocwithattachment","test.html")
266
+ attachment.should == @attach
267
+ end
268
+ it "should be there" do
269
+ attachment = @database.fetch_attachment("mydocwithattachment","other.html")
270
+ attachment.should == @attach2
271
+ end
272
+ end
273
+
274
+
275
+ describe "POST document with attachment (with funky name)" do
276
+ before(:each) do
277
+ @attach = "<html><head><title>My Funky Doc</title></head><body><p>Has words.</p></body></html>"
278
+ @doc = {
279
+ "field" => ["some other value"],
280
+ "_attachments" => {
281
+ "http://example.com/stuff.cgi?things=and%20stuff" => {
282
+ "type" => "text/html",
283
+ "data" => @attach
284
+ }
285
+ }
286
+ }
287
+ @docid = @database.save(@doc)['id']
288
+ end
289
+ it "should save and be indicated" do
290
+ doc = @database.get(@docid)
291
+ doc['_attachments']['http://example.com/stuff.cgi?things=and%20stuff']['length'].should == @attach.length
292
+ end
293
+ it "should be there" do
294
+ attachment = @database.fetch_attachment(@docid,"http://example.com/stuff.cgi?things=and%20stuff")
295
+ attachment.should == @attach
296
+ end
297
+ end
298
+
299
+ describe "PUT (new document with url id)" do
300
+ it "should create the document" do
301
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
302
+ @database.save({'_id' => @docid, 'will-exist' => 'here'})
303
+ lambda{@database.save({'_id' => @docid})}.should raise_error(RestClient::Request::RequestFailed)
304
+ @database.get(@docid)['will-exist'].should == 'here'
305
+ end
306
+ end
307
+
308
+
309
+ describe "PUT (new document with id)" do
310
+ it "should start without the document" do
311
+ # r = @database.save({'lemons' => 'from texas', 'and' => 'spain'})
312
+ @database.documents['rows'].each do |doc|
313
+ doc['id'].should_not == 'my-doc'
314
+ end
315
+ # should_not include({'_id' => 'my-doc'})
316
+ # this needs to be a loop over docs on content with the post
317
+ # or instead make it return something with a fancy <=> method
318
+ end
319
+ it "should create the document" do
320
+ @database.save({'_id' => 'my-doc', 'will-exist' => 'here'})
321
+ lambda{@database.save({'_id' => 'my-doc'})}.should raise_error(RestClient::Request::RequestFailed)
322
+ end
323
+ end
324
+
325
+ describe "PUT (existing document with rev)" do
326
+ before(:each) do
327
+ @database.save({'_id' => 'my-doc', 'will-exist' => 'here'})
328
+ @doc = @database.get('my-doc')
329
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
330
+ @database.save({'_id' => @docid, 'now' => 'save'})
331
+ end
332
+ it "should start with the document" do
333
+ @doc['will-exist'].should == 'here'
334
+ @database.get(@docid)['now'].should == 'save'
335
+ end
336
+ it "should save with url id" do
337
+ doc = @database.get(@docid)
338
+ doc['yaml'] = ['json', 'word.']
339
+ @database.save doc
340
+ @database.get(@docid)['yaml'].should == ['json', 'word.']
341
+ end
342
+ it "should fail to resave without the rev" do
343
+ @doc['them-keys'] = 'huge'
344
+ @doc['_rev'] = 'wrong'
345
+ # @database.save(@doc)
346
+ lambda {@database.save(@doc)}.should raise_error
347
+ end
348
+ it "should update the document" do
349
+ @doc['them-keys'] = 'huge'
350
+ @database.save(@doc)
351
+ now = @database.get('my-doc')
352
+ now['them-keys'].should == 'huge'
353
+ end
354
+ end
355
+
356
+ describe "DELETE existing document" do
357
+ before(:each) do
358
+ @r = @database.save({'lemons' => 'from texas', 'and' => 'spain'})
359
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
360
+ @database.save({'_id' => @docid, 'will-exist' => 'here'})
361
+ end
362
+ it "should work" do
363
+ doc = @database.get(@r['id'])
364
+ doc['and'].should == 'spain'
365
+ @database.delete doc
366
+ lambda{@database.get @r['id']}.should raise_error
367
+ end
368
+ it "should work with uri id" do
369
+ doc = @database.get(@docid)
370
+ @database.delete doc
371
+ lambda{@database.get @docid}.should raise_error
372
+ end
373
+
374
+ it 'should work with document id an revision id' do
375
+ doc = @database.get(@docid)
376
+ @database.delete(@docid, doc['_rev'])
377
+ lambda { @database.get(@docid) }.should raise_error
378
+ end
379
+ end
380
+
381
+ it "should list documents" do
382
+ 5.times do
383
+ @database.save({'another' => 'doc', 'will-exist' => 'anywhere'})
384
+ end
385
+ ds = @database.documents
386
+ ds['rows'].should be_an_instance_of(Array)
387
+ ds['rows'][0]['id'].should_not be_nil
388
+ ds['total_rows'].should == 5
389
+ end
390
+
391
+ it "should list documents with keys and such" do
392
+ 9.times do |i|
393
+ @database.save({'_id' => "doc#{i}",'another' => 'doc', 'will-exist' => 'here'})
394
+ end
395
+ ds = @database.documents
396
+ ds['rows'].should be_an_instance_of(Array)
397
+ ds['rows'][0]['id'].should == "doc0"
398
+ ds['total_rows'].should == 9
399
+ ds = @database.documents(:startkey => 'doc0', :endkey => 'doc3')
400
+ ds['rows'].length.should == 4
401
+ ds = @database.documents(:key => 'doc0')
402
+ ds['rows'].length.should == 1
403
+ end
404
+
405
+ describe "deleting a database" do
406
+ it "should start with the test database" do
407
+ @couch_rest.databases.should include('couchy-test')
408
+ end
409
+ it "should delete the database" do
410
+ db = @couch_rest.database('couchy-test')
411
+ # r =
412
+ db.delete!
413
+ # r['ok'].should == true
414
+ @couch_rest.databases.should_not include('couchy-test')
415
+ end
416
+ end
417
+ end