From bf1acd835553d05e5d17a4234559cdaeba4fc442 Mon Sep 17 00:00:00 2001 From: Chris Anderson Date: Sat, 7 Jun 2008 08:32:51 -0700 Subject: [PATCH] document attachments now supported --- lib/couch_rest.rb | 4 ++-- lib/database.rb | 28 +++++++++++++++++++++++++-- script/couchview | 24 +++++++++++++---------- spec/couch_rest_spec.rb | 2 +- spec/database_spec.rb | 43 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/lib/couch_rest.rb b/lib/couch_rest.rb index 8d24f15..b6652dc 100644 --- a/lib/couch_rest.rb +++ b/lib/couch_rest.rb @@ -7,7 +7,7 @@ require File.dirname(__FILE__) + '/database' class CouchRest attr_accessor :uri - def initialize server + def initialize server = 'http://localhost:5984' @uri = server end @@ -38,7 +38,7 @@ class CouchRest end def get uri - JSON.parse(RestClient.get(uri)) + JSON.parse(RestClient.get(uri), :max_nesting => false) end def post uri, doc = nil diff --git a/lib/database.rb b/lib/database.rb index 7953c73..ec9c3f5 100644 --- a/lib/database.rb +++ b/lib/database.rb @@ -1,4 +1,5 @@ require 'cgi' +require "base64" class CouchRest class Database @@ -25,12 +26,21 @@ class CouchRest end def get id - slug = CGI.escape(id) + slug = CGI.escape(id) CouchRest.get "#{@root}/#{slug}" end - # PUT or POST depending on precense of _id attribute + def fetch_attachment doc, name + doc = CGI.escape(doc) + name = CGI.escape(name) + RestClient.get "#{@root}/#{doc}/#{name}" + end + + # PUT or POST depending on presence of _id attribute def save doc + if doc['_attachments'] + doc['_attachments'] = encode_attachments(doc['_attachments']) + end if doc['_id'] slug = CGI.escape(doc['_id']) CouchRest.put "#{@root}/#{slug}", doc @@ -51,5 +61,19 @@ class CouchRest def delete! CouchRest.delete @root end + private + def encode_attachments attachments + result = {} + attachments.each do |k,v| + result[k] = { + "type" => "base64", + "data" => base64(v) + } + end + result + end + def base64 data + Base64.encode64(data).gsub(/\s/,'') + end end end \ No newline at end of file diff --git a/script/couchview b/script/couchview index 8328667..14bbe28 100755 --- a/script/couchview +++ b/script/couchview @@ -98,26 +98,30 @@ when "push" # files to views end designs = all.group_by{|f|f[0]} designs.each do |design,parts| - puts "design #{design}" + # puts "replace _design/#{design}? (enter to proceed, 'n' to skip)" + # rep = $stdin.gets.chomp + # next if rep == 'n' dviews = {} parts.group_by{|p|p[1]}.each do |view,fs| fs.each do |f| dviews["#{view}-reduce"] ||= {} dviews["#{view}-reduce"][f[2]] = readjs(f.last,libs) end - dviews["#{view}-map"] = {:map => dviews["#{view}-reduce"]['map']} + dviews["#{view}-map"] = {'map' => dviews["#{view}-reduce"]['map']} dviews.delete("#{view}-reduce") unless dviews["#{view}-reduce"]["reduce"] end # save them to the db - begin - view = db.get("_design/#{design}") - db.delete(view) - rescue + view = db.get("_design/#{design}") rescue nil + if (view && view['views'] == dviews) + puts "no change to _design/#{design}. skipping..." + else + puts "replacing _design/#{design}" + db.delete(view) rescue nil + db.save({ + "_id" => "_design/#{design}", + :views => dviews + }) end - db.save({ - "_id" => "_design/#{design}", - :views => dviews - }) end when "pull" # views to files diff --git a/spec/couch_rest_spec.rb b/spec/couch_rest_spec.rb index a49e97a..f4099f8 100644 --- a/spec/couch_rest_spec.rb +++ b/spec/couch_rest_spec.rb @@ -23,7 +23,7 @@ describe CouchRest do v = @cr.info["version"] vi = v.split(/a/).pop.to_i vi.should be >= 661484 # versions older than this will likely fail many specs - vi.should be <= 661484 # versions newer than this haven't been tried + vi.should be <= 663797 # versions newer than this haven't been tried end end diff --git a/spec/database_spec.rb b/spec/database_spec.rb index 5c54df7..dd850a7 100644 --- a/spec/database_spec.rb +++ b/spec/database_spec.rb @@ -183,6 +183,49 @@ describe CouchRest::Database do end end + describe "PUT document with attachment" do + before(:each) do + @attach = "My Doc

Has words.

" + @doc = { + "_id" => "mydocwithattachment", + "field" => ["some value"], + "_attachments" => { + "test.html" => @attach + } + } + @db.save(@doc) + end + it "should save and be indicated" do + doc = @db.get("mydocwithattachment") + doc['_attachments']['test.html']['length'].should == @attach.length + end + it "should be there" do + attachment = @db.fetch_attachment("mydocwithattachment","test.html") + attachment.should == @attach + end + end + + describe "POST document with attachment (with funky name)" do + before(:each) do + @attach = "My Funky Doc

Has words.

" + @doc = { + "field" => ["some other value"], + "_attachments" => { + "http://example.com/stuff.cgi?things=and%20stuff" => @attach + } + } + @docid = @db.save(@doc)['id'] + end + it "should save and be indicated" do + doc = @db.get(@docid) + doc['_attachments']['http://example.com/stuff.cgi?things=and%20stuff']['length'].should == @attach.length + end + it "should be there" do + attachment = @db.fetch_attachment(@docid,"http://example.com/stuff.cgi?things=and%20stuff") + attachment.should == @attach + end + end + describe "PUT (new document with url id)" do it "should create the document" do @docid = "http://example.com/stuff.cgi?things=and%20stuff"