dpla-couchrest 1.2.1.pre.dpla

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 (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +176 -0
  6. data/README.md +66 -0
  7. data/Rakefile +23 -0
  8. data/THANKS.md +21 -0
  9. data/VERSION +1 -0
  10. data/couchrest.gemspec +36 -0
  11. data/examples/word_count/markov +38 -0
  12. data/examples/word_count/views/books/chunked-map.js +3 -0
  13. data/examples/word_count/views/books/united-map.js +1 -0
  14. data/examples/word_count/views/markov/chain-map.js +6 -0
  15. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  16. data/examples/word_count/views/word_count/count-map.js +6 -0
  17. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  18. data/examples/word_count/word_count.rb +46 -0
  19. data/examples/word_count/word_count_query.rb +40 -0
  20. data/examples/word_count/word_count_views.rb +26 -0
  21. data/history.txt +214 -0
  22. data/init.rb +1 -0
  23. data/lib/couchrest.rb +146 -0
  24. data/lib/couchrest/attributes.rb +89 -0
  25. data/lib/couchrest/commands/generate.rb +71 -0
  26. data/lib/couchrest/commands/push.rb +103 -0
  27. data/lib/couchrest/database.rb +402 -0
  28. data/lib/couchrest/design.rb +91 -0
  29. data/lib/couchrest/document.rb +105 -0
  30. data/lib/couchrest/helper/attachments.rb +29 -0
  31. data/lib/couchrest/helper/pager.rb +103 -0
  32. data/lib/couchrest/helper/streamer.rb +60 -0
  33. data/lib/couchrest/helper/upgrade.rb +51 -0
  34. data/lib/couchrest/middlewares/logger.rb +263 -0
  35. data/lib/couchrest/monkeypatches.rb +25 -0
  36. data/lib/couchrest/rest_api.rb +166 -0
  37. data/lib/couchrest/server.rb +92 -0
  38. data/lib/couchrest/support/inheritable_attributes.rb +107 -0
  39. data/spec/.gitignore +1 -0
  40. data/spec/couchrest/couchrest_spec.rb +197 -0
  41. data/spec/couchrest/database_spec.rb +914 -0
  42. data/spec/couchrest/design_spec.rb +206 -0
  43. data/spec/couchrest/document_spec.rb +400 -0
  44. data/spec/couchrest/helpers/pager_spec.rb +115 -0
  45. data/spec/couchrest/helpers/streamer_spec.rb +134 -0
  46. data/spec/couchrest/rest_api_spec.rb +241 -0
  47. data/spec/couchrest/server_spec.rb +35 -0
  48. data/spec/fixtures/attachments/README +3 -0
  49. data/spec/fixtures/attachments/couchdb.png +0 -0
  50. data/spec/fixtures/attachments/test.html +11 -0
  51. data/spec/fixtures/views/lib.js +3 -0
  52. data/spec/fixtures/views/test_view/lib.js +3 -0
  53. data/spec/fixtures/views/test_view/only-map.js +4 -0
  54. data/spec/fixtures/views/test_view/test-map.js +3 -0
  55. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  56. data/spec/spec.opts +5 -0
  57. data/spec/spec_helper.rb +46 -0
  58. data/utils/remap.rb +27 -0
  59. data/utils/subset.rb +30 -0
  60. metadata +212 -0
@@ -0,0 +1,206 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
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
+ @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
+ @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
+ @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
+ it "should be queryable on specified database" do
61
+ @des.name = "mydesign"
62
+ @des.save
63
+ @des.database = nil
64
+ res = @des.view_on @db, :by_name
65
+ res["rows"][0]["key"].should == "x"
66
+ end
67
+ end
68
+
69
+ describe "from a saved document" do
70
+ before(:each) do
71
+ @db = reset_test_db!
72
+ @db.save_doc({
73
+ "_id" => "_design/test",
74
+ "views" => {
75
+ "by_name" => {
76
+ "map" => "function(doc){if (doc.name) emit(doc.name, null)}"
77
+ }
78
+ }
79
+ })
80
+ @db.bulk_save([{"name" => "a"},{"name" => "b"}])
81
+ @des = @db.get "_design/test"
82
+ end
83
+ it "should be a Design" do
84
+ @des.should be_an_instance_of(CouchRest::Design)
85
+ end
86
+ it "should have a modifiable name" do
87
+ @des.name.should == "test"
88
+ @des.name = "supertest"
89
+ @des.id.should == "_design/supertest"
90
+ end
91
+ it "should by queryable" do
92
+ res = @des.view :by_name
93
+ res["rows"][0]["key"].should == "a"
94
+ end
95
+ end
96
+
97
+ describe "a view with default options" do
98
+ before(:all) do
99
+ @db = reset_test_db!
100
+ @des = CouchRest::Design.new
101
+ @des.name = "test"
102
+ @des.view_by :name, :descending => true
103
+ @des.database = @db
104
+ @des.save
105
+ @db.bulk_save([{"name" => "a"},{"name" => "z"}])
106
+ end
107
+ it "should save them" do
108
+ @d2 = @db.get(@des.id)
109
+ @d2["views"]["by_name"]["couchrest-defaults"].should == {"descending"=>true}
110
+ end
111
+ it "should use them" do
112
+ res = @des.view :by_name
113
+ res["rows"].first["key"].should == "z"
114
+ end
115
+ it "should override them" do
116
+ res = @des.view :by_name, :descending => false
117
+ res["rows"].first["key"].should == "a"
118
+ end
119
+ end
120
+
121
+ describe "a view with multiple keys" do
122
+ before(:all) do
123
+ @db = reset_test_db!
124
+ @des = CouchRest::Design.new
125
+ @des.name = "test"
126
+ @des.view_by :name, :age
127
+ @des.database = @db
128
+ @des.save
129
+ @db.bulk_save([{"name" => "a", "age" => 2},
130
+ {"name" => "a", "age" => 4},{"name" => "z", "age" => 9}])
131
+ end
132
+ it "should work" do
133
+ res = @des.view :by_name_and_age
134
+ res["rows"].first["key"].should == ["a",2]
135
+ end
136
+ end
137
+
138
+ describe "a view with nil and 0 values" do
139
+ before(:all) do
140
+ @db = reset_test_db!
141
+ @des = CouchRest::Design.new
142
+ @des.name = "test"
143
+ @des.view_by :code
144
+ @des.database = @db
145
+ @des.save
146
+ @db.bulk_save([{"code" => "a", "age" => 2},
147
+ {"code" => nil, "age" => 4},{"code" => 0, "age" => 9}])
148
+ end
149
+ it "should work" do
150
+ res = @des.view :by_code
151
+ res["rows"][0]["key"].should == 0
152
+ res["rows"][1]["key"].should == "a"
153
+ res["rows"][2].should be_nil
154
+ end
155
+ end
156
+
157
+ describe "a view with nil and 0 values and :allow_nil" do
158
+ before(:all) do
159
+ @db = reset_test_db!
160
+ @des = CouchRest::Design.new
161
+ @des.name = "test"
162
+ @des.view_by :code, :allow_nil => true
163
+ @des.database = @db
164
+ @des.save
165
+ @db.bulk_save([{"code" => "a", "age" => 2},
166
+ {"code" => nil, "age" => 4},{"code" => 0, "age" => 9}])
167
+ end
168
+ it "should work" do
169
+ res = @des.view :by_code
170
+ res["rows"][0]["key"].should == nil
171
+ res["rows"][1]["key"].should == 0
172
+ res["rows"][2]["key"].should == "a"
173
+ end
174
+ end
175
+
176
+
177
+ describe "a view with a reduce function" do
178
+ before(:all) do
179
+ @db = reset_test_db!
180
+ @des = CouchRest::Design.new
181
+ @des.name = "test"
182
+ @des.view_by :code, :map => "function(d){ if(d['code']) { emit(d['code'], 1); } }", :reduce => "function(k,v,r){ return sum(v); }"
183
+ @des.database = @db
184
+ @des.save
185
+ @db.bulk_save([{"code" => "a", "age" => 2},
186
+ {"code" => 'b', "age" => 4},{"code" => 'c', "age" => 9}])
187
+ end
188
+ it "should not set a default parameter" do
189
+ @des['views']['by_code']['couchrest-defaults'].should be_nil
190
+ end
191
+ it "should include reduce parameter in query" do
192
+ # this would fail without it
193
+ res = @des.view :by_code
194
+ res["rows"][0]["key"].should == 'a'
195
+ end
196
+ it "should allow reduce to be performed" do
197
+ res = @des.view :by_code, :reduce => true
198
+ res["rows"][0]["value"].should eql(3)
199
+ end
200
+ it "does not allow string keys to be passed to view as options" do
201
+ lambda{ @des.view :by_code, 'reduce' => true }.should raise_error(ArgumentError, /set as symbols/)
202
+ end
203
+ end
204
+
205
+
206
+ end
@@ -0,0 +1,400 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ class Video < CouchRest::Document; end
4
+
5
+ describe CouchRest::Document do
6
+
7
+ before(:all) do
8
+ @couch = CouchRest.new
9
+ @db = @couch.database!(TESTDB)
10
+ end
11
+
12
+ describe "#new" do
13
+ it "should not be a Hash" do
14
+ @doc = CouchRest::Document.new
15
+ @doc.class.should eql(CouchRest::Document)
16
+ @doc.is_a?(Hash).should be_false
17
+ end
18
+
19
+ it "should be possible to initialize a new Document with attributes" do
20
+ @doc = CouchRest::Document.new('foo' => 'bar', :test => 'foo')
21
+ @doc['foo'].should eql('bar')
22
+ @doc['test'].should eql('foo')
23
+ end
24
+
25
+ it "should accept new with _id" do
26
+ @doc = CouchRest::Document.new('_id' => 'sample', 'foo' => 'bar')
27
+ @doc['_id'].should eql('sample')
28
+ @doc['foo'].should eql('bar')
29
+ end
30
+
31
+ context "replacing initalize" do
32
+ it "should not raise error" do
33
+ klass = Class.new(CouchRest::Document)
34
+ klass.class_eval do
35
+ def initialize; end # don't do anything, just overwrite
36
+ end
37
+ expect {
38
+ @doc = klass.new
39
+ @doc['test'] = 'sample'
40
+ }.to_not raise_error
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ describe "hash methods" do
47
+ it "should respond to forwarded hash methods" do
48
+ @doc = CouchRest::Document.new(:foo => 'bar')
49
+ [:to_a, :==, :eql?, :keys, :values, :each, :reject, :reject!, :empty?,
50
+ :clear, :merge, :merge!, :encode_json, :as_json, :to_json, :frozen?].each do |call|
51
+ @doc.should respond_to(call)
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "[]=" do
57
+ before(:each) do
58
+ @doc = CouchRest::Document.new
59
+ end
60
+ it "should work" do
61
+ @doc["enamel"].should == nil
62
+ @doc["enamel"] = "Strong"
63
+ @doc["enamel"].should == "Strong"
64
+ end
65
+ it "[]= should convert to string" do
66
+ @doc["enamel"].should == nil
67
+ @doc[:enamel] = "Strong"
68
+ @doc["enamel"].should == "Strong"
69
+ end
70
+ it "should read as a string" do
71
+ @doc[:enamel] = "Strong"
72
+ @doc[:enamel].should == "Strong"
73
+ end
74
+ end
75
+
76
+ describe "#has_key?" do
77
+ before :each do
78
+ @doc = CouchRest::Document.new
79
+ end
80
+ it "should confirm existance of key" do
81
+ @doc[:test] = 'example'
82
+ @doc.has_key?('test').should be_true
83
+ @doc.has_key?(:test).should be_true
84
+ end
85
+ it "should deny existance of key" do
86
+ @doc.has_key?(:bardom).should be_false
87
+ @doc.has_key?('bardom').should be_false
88
+ end
89
+ end
90
+
91
+ describe "#dup" do
92
+ it "should also clone the attributes" do
93
+ @doc = CouchRest::Document.new('foo' => 'bar')
94
+ @doc2 = @doc.dup
95
+ @doc2.delete('foo')
96
+ @doc2['foo'].should be_nil
97
+ @doc['foo'].should eql('bar')
98
+ end
99
+ end
100
+
101
+ describe "#clone" do
102
+ it "should also clone the attributes" do
103
+ @doc = CouchRest::Document.new('foo' => 'bar')
104
+ @doc2 = @doc.clone
105
+ @doc2.delete('foo')
106
+ @doc2['foo'].should be_nil
107
+ @doc['foo'].should eql('bar')
108
+ end
109
+ end
110
+
111
+ describe "#freeze" do
112
+ it "should freeze the attributes, but not actual model" do
113
+ klass = Class.new(CouchRest::Document)
114
+ klass.class_eval { attr_accessor :test_attr }
115
+ @doc = klass.new('foo' => 'bar')
116
+ @doc.freeze
117
+ lambda { @doc['foo'] = 'bar2' }.should raise_error(/frozen/)
118
+ lambda { @doc.test_attr = "bar3" }.should_not raise_error
119
+ end
120
+ end
121
+
122
+ describe "#as_couch_json" do
123
+ it "should provide a hash of data from normal document" do
124
+ @doc = CouchRest::Document.new('foo' => 'bar')
125
+ h = @doc.as_couch_json
126
+ h.should be_a(Hash)
127
+ h['foo'].should eql('bar')
128
+ end
129
+
130
+ it "should handle nested documents" do
131
+ @doc = CouchRest::Document.new('foo' => 'bar', 'doc' => CouchRest::Document.new('foo2' => 'bar2'))
132
+ h = @doc.as_couch_json
133
+ h['doc'].should be_a(Hash)
134
+ h['doc']['foo2'].should eql('bar2')
135
+ end
136
+ end
137
+
138
+ describe "#inspect" do
139
+ it "should provide a string of keys and values of the Response" do
140
+ @doc = CouchRest::Document.new('foo' => 'bar')
141
+ @doc.inspect.should eql("#<CouchRest::Document foo: \"bar\">")
142
+ end
143
+ end
144
+
145
+ describe "responding to Hash methods" do
146
+ it "should delegate requests" do
147
+ @doc = CouchRest::Document.new('foo' => 'bar')
148
+ @doc.keys.should eql(['foo'])
149
+ @doc.values.should eql(['bar'])
150
+ end
151
+ end
152
+
153
+ describe "default database" do
154
+ before(:each) do
155
+ Video.use_database nil
156
+ end
157
+ it "should be set using use_database on the model" do
158
+ Video.new.database.should be_nil
159
+ Video.use_database @db
160
+ Video.new.database.should == @db
161
+ Video.use_database nil
162
+ end
163
+
164
+ it "should be overwritten by instance" do
165
+ db = @couch.database('test')
166
+ article = Video.new
167
+ article.database.should be_nil
168
+ article.database = db
169
+ article.database.should_not be_nil
170
+ article.database.should == db
171
+ end
172
+ end
173
+
174
+ describe "new" do
175
+ before(:each) do
176
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
177
+ end
178
+ it "should create itself from a Hash" do
179
+ @doc["key"].should == [1,2,3]
180
+ @doc["more"].should == "values"
181
+ end
182
+ it "should not have rev and id" do
183
+ @doc.rev.should be_nil
184
+ @doc.id.should be_nil
185
+ end
186
+ it "should be possible to set id" do
187
+ @doc.id = 1
188
+ @doc.id.should eql(1)
189
+ end
190
+
191
+ it "should freak out when saving without a database" do
192
+ lambda{@doc.save}.should raise_error(ArgumentError)
193
+ end
194
+
195
+ end
196
+
197
+ # move to database spec
198
+ describe "saving using a database" do
199
+ before(:all) do
200
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
201
+ @db = reset_test_db!
202
+ @resp = @db.save_doc(@doc)
203
+ end
204
+ it "should apply the database" do
205
+ @doc.database.should == @db
206
+ end
207
+ it "should get id and rev" do
208
+ @doc.id.should == @resp["id"]
209
+ @doc.rev.should == @resp["rev"]
210
+ end
211
+ it "should generate a correct URI" do
212
+ @doc.uri.should == "#{@db.root}/#{@doc.id}"
213
+ URI.parse(@doc.uri).to_s.should == @doc.uri
214
+ end
215
+ it "should generate a correct URI with revision" do
216
+ @doc.uri(true).should == "#{@db.root}/#{@doc.id}?rev=#{@doc.rev}"
217
+ URI.parse(@doc.uri(true)).to_s.should == @doc.uri(true)
218
+ end
219
+ end
220
+
221
+ describe "bulk saving" do
222
+ before :all do
223
+ @db = reset_test_db!
224
+ end
225
+
226
+ it "should use the document bulk save cache" do
227
+ doc = CouchRest::Document.new({"_id" => "bulkdoc", "val" => 3})
228
+ doc.database = @db
229
+ doc.save(true)
230
+ lambda { doc.database.get(doc["_id"]) }.should raise_error(RestClient::ResourceNotFound)
231
+ doc.database.bulk_save
232
+ doc.database.get(doc["_id"])["val"].should == doc["val"]
233
+ end
234
+ end
235
+
236
+ describe "getting from a database" do
237
+ before(:all) do
238
+ @db = reset_test_db!
239
+ @resp = @db.save_doc({
240
+ "key" => "value"
241
+ })
242
+ @doc = @db.get @resp['id']
243
+ end
244
+ it "should return a document" do
245
+ @doc.should be_an_instance_of(CouchRest::Document)
246
+ end
247
+ it "should have a database" do
248
+ @doc.database.should == @db
249
+ end
250
+ it "should be saveable and resavable" do
251
+ @doc["more"] = "keys"
252
+ @doc.save
253
+ @db.get(@resp['id'])["more"].should == "keys"
254
+ @doc["more"] = "these keys"
255
+ @doc.save
256
+ @db.get(@resp['id'])["more"].should == "these keys"
257
+ end
258
+ end
259
+
260
+ describe "destroying a document from a db" do
261
+ before(:all) do
262
+ @db = reset_test_db!
263
+ @resp = @db.save_doc({
264
+ "key" => "value"
265
+ })
266
+ @doc = @db.get @resp['id']
267
+ end
268
+ it "should make it disappear" do
269
+ @doc.destroy
270
+ lambda{@db.get @resp['id']}.should raise_error
271
+ end
272
+ it "should error when there's no db" do
273
+ @doc = CouchRest::Document.new("key" => [1,2,3], :more => "values")
274
+ lambda{@doc.destroy}.should raise_error(ArgumentError)
275
+ end
276
+ end
277
+
278
+
279
+ describe "destroying a document from a db using bulk save" do
280
+ before(:all) do
281
+ @db = reset_test_db!
282
+ @resp = @db.save_doc({
283
+ "key" => "value"
284
+ })
285
+ @doc = @db.get @resp['id']
286
+ end
287
+ it "should defer actual deletion" do
288
+ @doc.destroy(true)
289
+ @doc['_id'].should == nil
290
+ @doc['_rev'].should == nil
291
+ lambda{@db.get @resp['id']}.should_not raise_error
292
+ @db.bulk_save
293
+ lambda{@db.get @resp['id']}.should raise_error
294
+ end
295
+ end
296
+
297
+ describe "copying a document" do
298
+ before :each do
299
+ @db = reset_test_db!
300
+ @resp = @db.save_doc({'key' => 'value'})
301
+ @docid = 'new-location'
302
+ @doc = @db.get(@resp['id'])
303
+ end
304
+ describe "to a new location" do
305
+ it "should work" do
306
+ @doc.copy @docid
307
+ newdoc = @db.get(@docid)
308
+ newdoc['key'].should == 'value'
309
+ end
310
+ it "should fail without a database" do
311
+ lambda{CouchRest::Document.new({"not"=>"a real doc"}).copy}.should raise_error(ArgumentError)
312
+ end
313
+ end
314
+ describe "to an existing location" do
315
+ before :each do
316
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
317
+ end
318
+ it "should fail without a rev" do
319
+ lambda{@doc.copy @docid}.should raise_error(RestClient::RequestFailed)
320
+ end
321
+ it "should succeed with a rev" do
322
+ @to_be_overwritten = @db.get(@docid)
323
+ @doc.copy "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
324
+ newdoc = @db.get(@docid)
325
+ newdoc['key'].should == 'value'
326
+ end
327
+ it "should succeed given the doc to overwrite" do
328
+ @to_be_overwritten = @db.get(@docid)
329
+ @doc.copy @to_be_overwritten
330
+ newdoc = @db.get(@docid)
331
+ newdoc['key'].should == 'value'
332
+ end
333
+ end
334
+ end
335
+ end
336
+
337
+ describe "dealing with attachments" do
338
+ before do
339
+ @db = reset_test_db!
340
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
341
+ response = @db.save_doc({'key' => 'value'})
342
+ @doc = @db.get(response['id'])
343
+ end
344
+
345
+ def append_attachment(name='test.html', attach=@attach)
346
+ @doc['_attachments'] ||= {}
347
+ @doc['_attachments'][name] = {
348
+ 'type' => 'text/html',
349
+ 'data' => attach
350
+ }
351
+ @doc.save
352
+ @rev = @doc['_rev']
353
+ end
354
+
355
+ describe "PUTing an attachment directly to the doc" do
356
+ before do
357
+ @doc.put_attachment('test.html', @attach)
358
+ end
359
+
360
+ it "is there" do
361
+ @db.fetch_attachment(@doc, 'test.html').should == @attach
362
+ end
363
+
364
+ it "updates the revision" do
365
+ @doc[:_rev].should_not == @rev
366
+ end
367
+
368
+ it "updates attachments" do
369
+ @attach2 = "<html><head><title>My Doc</title></head><body><p>Is Different.</p></body></html>"
370
+ @doc.put_attachment('test.html', @attach2)
371
+ @db.fetch_attachment(@doc, 'test.html').should == @attach2
372
+ end
373
+ end
374
+
375
+ describe "fetching an attachment from a doc directly" do
376
+ before do
377
+ append_attachment
378
+ end
379
+
380
+ it "pulls the attachment" do
381
+ @doc.fetch_attachment('test.html').should == @attach
382
+ end
383
+ end
384
+
385
+ describe "deleting an attachment from a doc directly" do
386
+ before do
387
+ append_attachment
388
+ @doc.delete_attachment('test.html')
389
+ end
390
+
391
+ it "removes it" do
392
+ lambda { @db.fetch_attachment(@doc, 'test.html').should }.should raise_error(RestClient::ResourceNotFound)
393
+ end
394
+
395
+ it "updates the revision" do
396
+ @doc[:_rev].should_not == @rev
397
+ end
398
+ end
399
+
400
+ end