support for couchdb's support for the COPY and MOVE verbs. depends on my commit to RestClient, currently only in b5d75acc68

I have considered adding this to the CouchRest::Document class as well ("@doc.copy new-id" and such) but haven't yet.
This commit is contained in:
Matt Lyon 2009-01-05 00:44:12 -08:00
parent a2aa4a9a3c
commit 9faa9daaca
3 changed files with 120 additions and 1 deletions

View file

@ -111,6 +111,14 @@ module CouchRest
JSON.parse(RestClient.delete(uri)) JSON.parse(RestClient.delete(uri))
end end
def copy uri, destination
JSON.parse(RestClient.copy(uri, {'Destination' => destination}))
end
def move uri, destination
JSON.parse(RestClient.move(uri, {'Destination' => destination}))
end
def paramify_url url, params = {} def paramify_url url, params = {}
if params && !params.empty? if params && !params.empty?
query = params.collect do |k,v| query = params.collect do |k,v|

View file

@ -172,6 +172,34 @@ module CouchRest
CouchRest.delete "#{@root}/#{slug}?rev=#{doc['_rev']}" CouchRest.delete "#{@root}/#{slug}?rev=#{doc['_rev']}"
end end
# COPY an existing document to a new id. If the destination id currently exists, a rev must be provided.
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
# hash with a '_rev' key
def copy doc, dest
raise ArgumentError, "_id is required for copying" unless doc['_id']
slug = CGI.escape(doc['_id'])
destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev']
"#{dest['_id']}?rev=#{dest['_rev']}"
else
dest
end
CouchRest.copy "#{@root}/#{slug}", destination
end
# MOVE an existing document to a new id. If the destination id currently exists, a rev must be provided.
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
# hash with a '_rev' key
def move doc, dest
raise ArgumentError, "_id and _rev are required for moving" unless doc['_id'] && doc['_rev']
slug = CGI.escape(doc['_id'])
destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev']
"#{dest['_id']}?rev=#{dest['_rev']}"
else
dest
end
CouchRest.move "#{@root}/#{slug}?rev=#{doc['_rev']}", destination
end
# Compact the database, removing old document revisions and optimizing space use. # Compact the database, removing old document revisions and optimizing space use.
def compact! def compact!
CouchRest.post "#{@root}/_compact" CouchRest.post "#{@root}/_compact"

View file

@ -474,6 +474,89 @@ describe CouchRest::Database do
end end
end end
describe "COPY existing document" do
before :each do
@r = @db.save({'artist' => 'Zappa', 'title' => 'Muffin Man'})
@docid = 'tracks/zappa/muffin-man'
@doc = @db.get(@r['id'])
end
describe "to a new location" do
it "should work" do
@db.copy @doc, @docid
newdoc = @db.get(@docid)
debugger
newdoc['artist'].should == 'Zappa'
end
it "should fail without an _id" do
lambda{@db.copy({"not"=>"a real doc"})}.should raise_error(ArgumentError)
end
end
describe "to an existing location" do
before :each do
@db.save({'_id' => @docid, 'will-exist' => 'here'})
end
it "should fail without a rev" do
lambda{@db.copy @doc, @docid}.should raise_error(RestClient::RequestFailed)
end
it "should succeed with a rev" do
@to_be_overwritten = @db.get(@docid)
@db.copy @doc, "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
newdoc = @db.get(@docid)
newdoc['artist'].should == 'Zappa'
end
it "should succeed given the doc to overwrite" do
@to_be_overwritten = @db.get(@docid)
@db.copy @doc, @to_be_overwritten
newdoc = @db.get(@docid)
newdoc['artist'].should == 'Zappa'
end
end
end
describe "MOVE existing document" do
before :each do
@r = @db.save({'artist' => 'Zappa', 'title' => 'Muffin Man'})
@docid = 'tracks/zappa/muffin-man'
@doc = @db.get(@r['id'])
end
describe "to a new location" do
it "should work" do
@db.move @doc, @docid
newdoc = @db.get(@docid)
newdoc['artist'].should == 'Zappa'
lambda {@db.get(@r['id'])}.should raise_error(RestClient::ResourceNotFound)
end
it "should fail without an _id or _rev" do
lambda{@db.move({"not"=>"a real doc"})}.should raise_error(ArgumentError)
lambda{@db.move({"_id"=>"not a real doc"})}.should raise_error(ArgumentError)
end
end
describe "to an existing location" do
before :each do
@db.save({'_id' => @docid, 'will-exist' => 'here'})
end
it "should fail without a rev" do
lambda{@db.move @doc, @docid}.should raise_error(RestClient::RequestFailed)
lambda{@db.get(@r['id'])}.should_not raise_error
end
it "should succeed with a rev" do
@to_be_overwritten = @db.get(@docid)
@db.move @doc, "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
newdoc = @db.get(@docid)
newdoc['artist'].should == 'Zappa'
lambda {@db.get(@r['id'])}.should raise_error(RestClient::ResourceNotFound)
end
it "should succeed given the doc to overwrite" do
@to_be_overwritten = @db.get(@docid)
@db.move @doc, @to_be_overwritten
newdoc = @db.get(@docid)
newdoc['artist'].should == 'Zappa'
lambda {@db.get(@r['id'])}.should raise_error(RestClient::ResourceNotFound)
end
end
end
it "should list documents" do it "should list documents" do
5.times do 5.times do
@db.save({'another' => 'doc', 'will-exist' => 'anywhere'}) @db.save({'another' => 'doc', 'will-exist' => 'anywhere'})