diff --git a/lib/couchrest/core/database.rb b/lib/couchrest/core/database.rb index b9d276b..9e25fc9 100644 --- a/lib/couchrest/core/database.rb +++ b/lib/couchrest/core/database.rb @@ -165,9 +165,16 @@ module CouchRest # DELETE the document from CouchDB that has the given _id and # _rev. - def delete doc - raise ArgumentError, "_id and _rev required for deleting" unless doc['_id'] && doc['_rev'] - + # + # If bulk is true (false by default) the deletion is recorded for bulk-saving (bulk-deletion :) later. + # Bulk saving happens automatically when #bulk_save_cache limit is exceded, or on the next non bulk save. + def delete (doc, bulk = false) + raise ArgumentError, "_id and _rev required for deleting" unless doc['_id'] && doc['_rev'] + if bulk + @bulk_save_cache << { '_id' => doc['_id'], '_rev' => doc['_rev'], '_deleted' => true } + return bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit + return { "ok" => true } # Mimic the non-deferred version + end slug = escape_docid(doc['_id']) CouchRest.delete "#{@root}/#{slug}?rev=#{doc['_rev']}" end diff --git a/lib/couchrest/core/document.rb b/lib/couchrest/core/document.rb index 71a5135..b47a7e0 100644 --- a/lib/couchrest/core/document.rb +++ b/lib/couchrest/core/document.rb @@ -45,9 +45,11 @@ module CouchRest # Deletes the document from the database. Runs the :delete callbacks. # Removes the _id and _rev fields, preparing the # document to be saved to a new _id. - def destroy + # If bulk is true (defaults to false) the document won't + # actually be deleted from the db until bulk save. + def destroy(bulk = false) raise ArgumentError, "doc.database required to destroy" unless database - result = database.delete self + result = database.delete(self, bulk) if result['ok'] self['_rev'] = nil self['_id'] = nil diff --git a/spec/couchrest/core/database_spec.rb b/spec/couchrest/core/database_spec.rb index 132d3c7..e84b5e3 100644 --- a/spec/couchrest/core/database_spec.rb +++ b/spec/couchrest/core/database_spec.rb @@ -472,6 +472,14 @@ describe CouchRest::Database do it "should fail without an _id" do lambda{@db.delete({"not"=>"a real doc"})}.should raise_error(ArgumentError) end + it "should defer actual deletion when using bulk save" do + doc = @db.get(@docid) + @db.delete doc, true + lambda{@db.get @docid}.should_not raise_error + @db.bulk_save + lambda{@db.get @docid}.should raise_error + end + end describe "COPY existing document" do diff --git a/spec/couchrest/core/document_spec.rb b/spec/couchrest/core/document_spec.rb index 485f638..0aef0bc 100644 --- a/spec/couchrest/core/document_spec.rb +++ b/spec/couchrest/core/document_spec.rb @@ -109,3 +109,22 @@ describe "destroying a document from a db" do lambda{@doc.destroy}.should raise_error(ArgumentError) end end + + +describe "destroying a document from a db using bulk save" do + before(:all) do + @db = reset_test_db! + @resp = @db.save({ + "key" => "value" + }) + @doc = @db.get @resp['id'] + end + it "should defer actual deletion" do + @doc.destroy(true) + @doc['_id'].should == nil + @doc['_rev'].should == nil + lambda{@db.get @resp['id']}.should_not raise_error + @db.bulk_save + lambda{@db.get @resp['id']}.should raise_error + end +end