Merge commit 'mattetti/master'

This commit is contained in:
Peter Gumeson 2009-06-11 21:18:37 -07:00
commit fc18b47800
7 changed files with 52 additions and 23 deletions

View file

@ -17,7 +17,8 @@ module CouchRest
@name = name @name = name
@server = server @server = server
@host = server.uri @host = server.uri
@uri = @root = "#{host}/#{name.gsub('/','%2F')}" @uri = "/#{name.gsub('/','%2F')}"
@root = host + uri
@streamer = Streamer.new(self) @streamer = Streamer.new(self)
@bulk_save_cache = [] @bulk_save_cache = []
@bulk_save_cache_limit = 500 # must be smaller than the uuid count @bulk_save_cache_limit = 500 # must be smaller than the uuid count
@ -25,18 +26,18 @@ module CouchRest
# returns the database's uri # returns the database's uri
def to_s def to_s
@uri @root
end end
# GET the database info from CouchDB # GET the database info from CouchDB
def info def info
CouchRest.get @uri CouchRest.get @root
end end
# Query the <tt>_all_docs</tt> view. Accepts all the same arguments as view. # Query the <tt>_all_docs</tt> view. Accepts all the same arguments as view.
def documents(params = {}) def documents(params = {})
keys = params.delete(:keys) keys = params.delete(:keys)
url = CouchRest.paramify_url "#{@uri}/_all_docs", params url = CouchRest.paramify_url "#{@root}/_all_docs", params
if keys if keys
CouchRest.post(url, {:keys => keys}) CouchRest.post(url, {:keys => keys})
else else
@ -56,7 +57,7 @@ module CouchRest
def slow_view(funcs, params = {}) def slow_view(funcs, params = {})
keys = params.delete(:keys) keys = params.delete(:keys)
funcs = funcs.merge({:keys => keys}) if keys funcs = funcs.merge({:keys => keys}) if keys
url = CouchRest.paramify_url "#{@uri}/_temp_view", params url = CouchRest.paramify_url "#{@root}/_temp_view", params
JSON.parse(RestClient.post(url, funcs.to_json, {"Content-Type" => 'application/json'})) JSON.parse(RestClient.post(url, funcs.to_json, {"Content-Type" => 'application/json'}))
end end
@ -70,7 +71,7 @@ module CouchRest
name = name.split('/') # I think this will always be length == 2, but maybe not... name = name.split('/') # I think this will always be length == 2, but maybe not...
dname = name.shift dname = name.shift
vname = name.join('/') vname = name.join('/')
url = CouchRest.paramify_url "#{@uri}/_design/#{dname}/_view/#{vname}", params url = CouchRest.paramify_url "#{@root}/_design/#{dname}/_view/#{vname}", params
if keys if keys
CouchRest.post(url, {:keys => keys}) CouchRest.post(url, {:keys => keys})
else else
@ -85,7 +86,7 @@ module CouchRest
# GET a document from CouchDB, by id. Returns a Ruby Hash. # GET a document from CouchDB, by id. Returns a Ruby Hash.
def get(id, params = {}) def get(id, params = {})
slug = escape_docid(id) slug = escape_docid(id)
url = CouchRest.paramify_url("#{@uri}/#{slug}", params) url = CouchRest.paramify_url("#{@root}/#{slug}", params)
result = CouchRest.get(url) result = CouchRest.get(url)
return result unless result.is_a?(Hash) return result unless result.is_a?(Hash)
doc = if /^_design/ =~ result["_id"] doc = if /^_design/ =~ result["_id"]
@ -101,7 +102,7 @@ module CouchRest
def fetch_attachment(doc, name) def fetch_attachment(doc, name)
# slug = escape_docid(docid) # slug = escape_docid(docid)
# name = CGI.escape(name) # name = CGI.escape(name)
uri = uri_for_attachment(doc, name) uri = url_for_attachment(doc, name)
RestClient.get uri RestClient.get uri
# "#{@uri}/#{slug}/#{name}" # "#{@uri}/#{slug}/#{name}"
end end
@ -110,13 +111,13 @@ module CouchRest
def put_attachment(doc, name, file, options = {}) def put_attachment(doc, name, file, options = {})
docid = escape_docid(doc['_id']) docid = escape_docid(doc['_id'])
name = CGI.escape(name) name = CGI.escape(name)
uri = uri_for_attachment(doc, name) uri = url_for_attachment(doc, name)
JSON.parse(RestClient.put(uri, file, options)) JSON.parse(RestClient.put(uri, file, options))
end end
# DELETE an attachment directly from CouchDB # DELETE an attachment directly from CouchDB
def delete_attachment doc, name def delete_attachment doc, name
uri = uri_for_attachment(doc, name) uri = url_for_attachment(doc, name)
# this needs a rev # this needs a rev
JSON.parse(RestClient.delete(uri)) JSON.parse(RestClient.delete(uri))
end end
@ -144,18 +145,18 @@ module CouchRest
result = if doc['_id'] result = if doc['_id']
slug = escape_docid(doc['_id']) slug = escape_docid(doc['_id'])
begin begin
CouchRest.put "#{@uri}/#{slug}", doc CouchRest.put "#{@root}/#{slug}", doc
rescue RestClient::ResourceNotFound rescue RestClient::ResourceNotFound
p "resource not found when saving even tho an id was passed" p "resource not found when saving even tho an id was passed"
slug = doc['_id'] = @server.next_uuid slug = doc['_id'] = @server.next_uuid
CouchRest.put "#{@uri}/#{slug}", doc CouchRest.put "#{@root}/#{slug}", doc
end end
else else
begin begin
slug = doc['_id'] = @server.next_uuid slug = doc['_id'] = @server.next_uuid
CouchRest.put "#{@uri}/#{slug}", doc CouchRest.put "#{@root}/#{slug}", doc
rescue #old version of couchdb rescue #old version of couchdb
CouchRest.post @uri, doc CouchRest.post @root, doc
end end
end end
if result['ok'] if result['ok']
@ -190,7 +191,7 @@ module CouchRest
doc['_id'] = nextid if nextid doc['_id'] = nextid if nextid
end end
end end
CouchRest.post "#{@uri}/_bulk_docs", {:docs => docs} CouchRest.post "#{@root}/_bulk_docs", {:docs => docs}
end end
alias :bulk_delete :bulk_save alias :bulk_delete :bulk_save
@ -207,7 +208,7 @@ module CouchRest
return { "ok" => true } # Mimic the non-deferred version return { "ok" => true } # Mimic the non-deferred version
end end
slug = escape_docid(doc['_id']) slug = escape_docid(doc['_id'])
CouchRest.delete "#{@uri}/#{slug}?rev=#{doc['_rev']}" CouchRest.delete "#{@root}/#{slug}?rev=#{doc['_rev']}"
end end
### DEPRECATION NOTICE ### DEPRECATION NOTICE
@ -227,7 +228,7 @@ module CouchRest
else else
dest dest
end end
CouchRest.copy "#{@uri}/#{slug}", destination CouchRest.copy "#{@root}/#{slug}", destination
end end
### DEPRECATION NOTICE ### DEPRECATION NOTICE
@ -238,7 +239,7 @@ module CouchRest
# 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 "#{@uri}/_compact" CouchRest.post "#{@root}/_compact"
end end
# Create the database # Create the database
@ -272,7 +273,7 @@ module CouchRest
# catastrophic. Use with care! # catastrophic. Use with care!
def delete! def delete!
clear_extended_doc_fresh_cache clear_extended_doc_fresh_cache
CouchRest.delete @uri CouchRest.delete @root
end end
private private
@ -280,7 +281,7 @@ module CouchRest
def clear_extended_doc_fresh_cache def clear_extended_doc_fresh_cache
::CouchRest::ExtendedDocument.subclasses.each{|klass| klass.design_doc_fresh = false if klass.respond_to?(:design_doc_fresh=) } ::CouchRest::ExtendedDocument.subclasses.each{|klass| klass.design_doc_fresh = false if klass.respond_to?(:design_doc_fresh=) }
end end
def uri_for_attachment(doc, name) def uri_for_attachment(doc, name)
if doc.is_a?(String) if doc.is_a?(String)
puts "CouchRest::Database#fetch_attachment will eventually require a doc as the first argument, not a doc.id" puts "CouchRest::Database#fetch_attachment will eventually require a doc as the first argument, not a doc.id"
@ -293,7 +294,11 @@ module CouchRest
docid = escape_docid(docid) docid = escape_docid(docid)
name = CGI.escape(name) name = CGI.escape(name)
rev = "?rev=#{doc['_rev']}" if rev rev = "?rev=#{doc['_rev']}" if rev
"#{@root}/#{docid}/#{name}#{rev}" "/#{docid}/#{name}#{rev}"
end
def url_for_attachment(doc, name)
@root + uri_for_attachment(doc, name)
end end
def escape_docid id def escape_docid id

View file

@ -68,7 +68,7 @@ module CouchRest
# Returns the CouchDB uri for the document # Returns the CouchDB uri for the document
def uri(append_rev = false) def uri(append_rev = false)
return nil if new? return nil if new?
couch_uri = "http://#{database.uri}/#{CGI.escape(id)}" couch_uri = "http://#{database.root}/#{CGI.escape(id)}"
if append_rev == true if append_rev == true
couch_uri << "?rev=#{rev}" couch_uri << "?rev=#{rev}"
elsif append_rev.kind_of?(Integer) elsif append_rev.kind_of?(Integer)

View file

@ -44,6 +44,12 @@ module CouchRest
"#{database.root}/#{self.id}/#{attachment_name}" "#{database.root}/#{self.id}/#{attachment_name}"
end end
# returns URI to fetch the attachment from
def attachment_uri(attachment_name)
return unless has_attachment?(attachment_name)
"#{database.uri}/#{self.id}/#{attachment_name}"
end
private private
def encode_attachment(data) def encode_attachment(data)

View file

@ -12,7 +12,8 @@ describe CouchRest::Database do
it "should escape the name in the URI" do it "should escape the name in the URI" do
db = @cr.database("foo/bar") db = @cr.database("foo/bar")
db.name.should == "foo/bar" db.name.should == "foo/bar"
db.uri.should == "#{COUCHHOST}/foo%2Fbar" db.root.should == "#{COUCHHOST}/foo%2Fbar"
db.uri.should == "/foo%2Fbar"
end end
end end

View file

@ -126,5 +126,10 @@ describe "ExtendedDocument attachments" do
it 'should return the attachment URL as specified by CouchDB HttpDocumentApi' do it 'should return the attachment URL as specified by CouchDB HttpDocumentApi' do
@obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}" @obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}"
end end
it 'should return the attachment URI' do
@obj.attachment_uri(@attachment_name).should == "#{Basic.database.uri}/#{@obj.id}/#{@attachment_name}"
end
end end
end end

View file

@ -1,4 +1,5 @@
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper') require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
require File.join(FIXTURE_PATH, 'more', 'person')
require File.join(FIXTURE_PATH, 'more', 'card') require File.join(FIXTURE_PATH, 'more', 'card')
require File.join(FIXTURE_PATH, 'more', 'invoice') require File.join(FIXTURE_PATH, 'more', 'invoice')
require File.join(FIXTURE_PATH, 'more', 'service') require File.join(FIXTURE_PATH, 'more', 'service')
@ -37,6 +38,15 @@ describe "ExtendedDocument properties" do
@card.family_name.should == @card.last_name @card.family_name.should == @card.last_name
end end
it "should let you use an alias for a casted attribute" do
@card.cast_alias = Person.new(:name => "Aimonetti")
@card.cast_alias.name.should == "Aimonetti"
@card.calias.name.should == "Aimonetti"
card = Card.new(:first_name => "matt", :cast_alias => {:name => "Aimonetti"})
card.cast_alias.name.should == "Aimonetti"
card.calias.name.should == "Aimonetti"
end
it "should be auto timestamped" do it "should be auto timestamped" do
@card.created_at.should be_nil @card.created_at.should be_nil
@card.updated_at.should be_nil @card.updated_at.should be_nil

View file

@ -11,6 +11,8 @@ class Card < CouchRest::ExtendedDocument
property :first_name property :first_name
property :last_name, :alias => :family_name property :last_name, :alias => :family_name
property :read_only_value, :read_only => true property :read_only_value, :read_only => true
property :cast_alias, :cast_as => 'Person', :alias => :calias
timestamps! timestamps!