sr-couchy 0.0.2

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 (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