couchrest 1.1.0.pre3 → 1.1.0

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.
@@ -1,3 +1,9 @@
1
+ == 1.1.0 - 2011-06-25
2
+
3
+ * Minor changes
4
+ * Refactored basic CouchRest API (get, post, etc.) to pass-through RestClient and MultiJSON options, including headers.
5
+ * CouchRest::Attributes module created to make attribute related methods independent.
6
+
1
7
  == 1.1.0.pre3 - 2011-06-06
2
8
 
3
9
  * Major changes
@@ -1,11 +1,11 @@
1
1
  # Copyright 2008 J. Chris Anderson
2
- #
2
+ #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
5
5
  # You may obtain a copy of the License at
6
- #
6
+ #
7
7
  # http://www.apache.org/licenses/LICENSE-2.0
8
- #
8
+ #
9
9
  # Unless required by applicable law or agreed to in writing, software
10
10
  # distributed under the License is distributed on an "AS IS" BASIS,
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -29,6 +29,7 @@ require 'forwardable'
29
29
 
30
30
  # = CouchDB, close to the metal
31
31
  module CouchRest
32
+ autoload :Attributes, 'couchrest/attributes'
32
33
  autoload :Server, 'couchrest/server'
33
34
  autoload :Database, 'couchrest/database'
34
35
  autoload :Document, 'couchrest/document'
@@ -80,7 +81,7 @@ module CouchRest
80
81
  end
81
82
 
82
83
  db = nil if db && db.empty?
83
-
84
+
84
85
  {
85
86
  :host => (scheme || "http://") + (host || "127.0.0.1:5984"),
86
87
  :database => db,
@@ -92,7 +93,7 @@ module CouchRest
92
93
  def proxy url
93
94
  RestClient.proxy = url
94
95
  end
95
-
96
+
96
97
  # ensure that a database exists
97
98
  # creates it if it isn't already there
98
99
  # returns it after it's been created
@@ -101,13 +102,13 @@ module CouchRest
101
102
  cr = CouchRest.new(parsed[:host])
102
103
  cr.database!(parsed[:database])
103
104
  end
104
-
105
+
105
106
  def database url
106
107
  parsed = parse url
107
108
  cr = CouchRest.new(parsed[:host])
108
109
  cr.database(parsed[:database])
109
110
  end
110
-
111
+
111
112
  def paramify_url url, params = {}
112
113
  if params && !params.empty?
113
114
  query = params.collect do |k,v|
@@ -0,0 +1,75 @@
1
+ #
2
+ # CouchRest::Attributes
3
+ #
4
+ # When included, provide the owner with an attributes hash and
5
+ # accessors that forward calls to it.
6
+ #
7
+ # Provides the basic functionality of Hash without actually being
8
+ # a Hash using Ruby's standard Forwardable module.
9
+ #
10
+ module CouchRest
11
+
12
+ module Attributes
13
+ extend Forwardable
14
+
15
+ # Initialize a new CouchRest Document and prepare
16
+ # a hidden attributes hash.
17
+ #
18
+ # When inherting a Document, it is essential that the
19
+ # super method is called before you own changes to ensure
20
+ # that the attributes hash has been initialized before
21
+ # you attempt to use it.
22
+ def initialize(attrs = nil)
23
+ @_attributes = {}
24
+ attrs.each{|k,v| self[k] = v} unless attrs.nil?
25
+ end
26
+
27
+ # Hash equivilent methods to access the attributes
28
+ def_delegators :@_attributes, :to_a, :==, :eql?, :keys, :values, :each,
29
+ :reject, :reject!, :empty?, :clear, :merge, :merge!,
30
+ :encode_json, :as_json, :to_json, :frozen?
31
+
32
+ def []=(key, value)
33
+ @_attributes[key.to_s] = value
34
+ end
35
+ def [](key)
36
+ @_attributes[key.to_s]
37
+ end
38
+ def has_key?(key)
39
+ @_attributes.has_key?(key.to_s)
40
+ end
41
+ def delete(key)
42
+ @_attributes.delete(key.to_s)
43
+ end
44
+ def dup
45
+ new = super
46
+ @_attributes = @_attributes.dup
47
+ new
48
+ end
49
+ def clone
50
+ new = super
51
+ @_attributes = @_attributes.dup
52
+ new
53
+ end
54
+ def to_hash
55
+ @_attributes
56
+ end
57
+
58
+ # Freeze the object's attributes instead of the actual document.
59
+ # This prevents further modifications to stored data, but does allow access
60
+ # to local variables useful for callbacks or cached data.
61
+ def freeze
62
+ @_attributes.freeze; self
63
+ end
64
+
65
+ # Provide details of the current keys in the reponse. Based on ActiveRecord::Base.
66
+ def inspect
67
+ attributes_as_nice_string = self.keys.collect { |key|
68
+ "#{key}: #{self[key].inspect}"
69
+ }.compact.join(", ")
70
+ "#<#{self.class} #{attributes_as_nice_string}>"
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -245,7 +245,7 @@ module CouchRest
245
245
  def view(name, params = {}, payload = {}, &block)
246
246
  payload['keys'] = params.delete(:keys) if params[:keys]
247
247
  # Try recognising the name, otherwise assume already prepared
248
- view_path = name =~ /^([^_].+?)\/(.*)$/ ? "_design/#{$1}/_view/#{$2}" : name
248
+ view_path = name_to_view_path(name)
249
249
  url = CouchRest.paramify_url "#{@root}/#{view_path}", params
250
250
  if block_given?
251
251
  if !payload.empty?
@@ -386,5 +386,11 @@ module CouchRest
386
386
  def base64(data)
387
387
  Base64.encode64(data).gsub(/\s/,'')
388
388
  end
389
+
390
+ # Convert a simplified view name into a complete view path. If
391
+ # the name already starts with a "_" no alterations will be made.
392
+ def name_to_view_path(name)
393
+ name =~ /^([^_].+?)\/(.*)$/ ? "_design/#{$1}/_view/#{$2}" : name
394
+ end
389
395
  end
390
396
  end
@@ -17,57 +17,13 @@
17
17
 
18
18
  module CouchRest
19
19
  class Document
20
- extend Forwardable
20
+ include CouchRest::Attributes
21
21
  include CouchRest::Attachments
22
22
  extend CouchRest::InheritableAttributes
23
23
 
24
24
  couchrest_inheritable_accessor :database
25
25
  attr_accessor :database
26
26
 
27
- # Initialize a new CouchRest Document and prepare
28
- # a hidden attributes hash.
29
- #
30
- # When inherting a Document, it is essential that the
31
- # super method is called before you own changes to ensure
32
- # that the attributes hash has been initialized before
33
- # you attempt to use it.
34
- def initialize(attrs = nil)
35
- @_attributes = {}
36
- attrs.each{|k,v| self[k] = v} unless attrs.nil?
37
- end
38
-
39
- # Hash equivilent methods to access the attributes
40
-
41
- def_delegators :@_attributes, :to_a, :==, :eql?, :keys, :values, :each,
42
- :reject, :reject!, :empty?, :clear, :merge, :merge!,
43
- :encode_json, :as_json, :to_json
44
-
45
- def []=(key, value)
46
- @_attributes[key.to_s] = value
47
- end
48
- def [](key)
49
- @_attributes[key.to_s]
50
- end
51
- def has_key?(key)
52
- @_attributes.has_key?(key.to_s)
53
- end
54
- def delete(key)
55
- @_attributes.delete(key.to_s)
56
- end
57
- def dup
58
- new = super
59
- @_attributes = @_attributes.dup
60
- new
61
- end
62
- def clone
63
- new = super
64
- @_attributes = @_attributes.dup
65
- new
66
- end
67
- def to_hash
68
- @_attributes
69
- end
70
-
71
27
  def id
72
28
  self['_id']
73
29
  end
@@ -135,14 +91,6 @@ module CouchRest
135
91
  @database || self.class.database
136
92
  end
137
93
 
138
- # Provide details of the current keys in the reponse. Based on ActiveRecord::Base.
139
- def inspect
140
- attributes_as_nice_string = self.keys.collect { |key|
141
- "#{key}: #{self[key].inspect}"
142
- }.compact.join(", ")
143
- "#<#{self.class} #{attributes_as_nice_string}>"
144
- end
145
-
146
94
  class << self
147
95
  # override the CouchRest::Model-wide default_database
148
96
  # This is not a thread safe operation, do not change the model
@@ -1,7 +1,75 @@
1
1
  module CouchRest
2
2
 
3
+ # CouchRest RestAPI
4
+ #
5
+ # The basic low-level interface for all REST requests to the database. Everything must pass
6
+ # through here before it is sent to the server.
7
+ #
8
+ # Five types of REST requests are supported: get, put, post, delete, and copy.
9
+ #
10
+ # Requests that do not have a payload, get, delete and copy, accept the URI and options parameters,
11
+ # where as put and post both expect a document as the second parameter.
12
+ #
13
+ # The API will try to intelegently split the options between the JSON parser and RestClient API.
14
+ #
15
+ # The following options will be recognised as header options and automatically added
16
+ # to the header hash:
17
+ #
18
+ # * :content_type, type of content to be sent, especially useful when sending files as this will set the file type. The default is :json.
19
+ # * :accept, the content type to accept in the response. This should pretty much always be :json.
20
+ #
21
+ # The following request options are supported:
22
+ #
23
+ # * :method override the requested method (should not be used!).
24
+ # * :url override the URL used in the request.
25
+ # * :payload override the document or data sent in the message body (only PUT or POST).
26
+ # * :headers any additional headers (overrides :content_type and :accept)
27
+ # * :timeout and :open_timeout the time in miliseconds to wait for the request, see RestClient API for more details.
28
+ # * :verify_ssl, :ssl_client_cert, :ssl_client_key, and :ssl_ca_file, SSL handling methods.
29
+ #
30
+ #
31
+ # Any other remaining options will be sent to the MultiJSON backend except for the :raw option.
32
+ #
33
+ # When :raw is true in PUT and POST requests, no attempt will be made to convert the document payload to JSON. This is
34
+ # not normally necessary as IO and Tempfile objects will not be parsed anyway. The result of the request will
35
+ # *always* be parsed.
36
+ #
37
+ # For all other requests, mainly GET, the :raw option will make no attempt to parse the result. This
38
+ # is useful for receiving files from the database.
39
+ #
40
+
3
41
  module RestAPI
4
42
 
43
+ # Send a GET request.
44
+ def get(uri, options = {})
45
+ execute(uri, :get, options)
46
+ end
47
+
48
+ # Send a PUT request.
49
+ def put(uri, doc = nil, options = {})
50
+ execute(uri, :put, options, doc)
51
+ end
52
+
53
+ # Send a POST request.
54
+ def post(uri, doc = nil, options = {})
55
+ execute(uri, :post, options, doc)
56
+ end
57
+
58
+ # Send a DELETE request.
59
+ def delete(uri, options = {})
60
+ execute(uri, :delete, options)
61
+ end
62
+
63
+ # Send a COPY request to the URI provided.
64
+ def copy(uri, destination, options = {})
65
+ opts = options.nil? ? {} : options.dup
66
+ # also copy headers!
67
+ opts[:headers] = options[:headers].nil? ? {} : options[:headers].dup
68
+ opts[:headers]['Destination'] = destination
69
+ execute(uri, :copy, opts)
70
+ end
71
+
72
+ # The default RestClient headers used in each request.
5
73
  def default_headers
6
74
  {
7
75
  :content_type => :json,
@@ -9,61 +77,60 @@ module CouchRest
9
77
  }
10
78
  end
11
79
 
12
- def get(uri, options = {})
13
- begin
14
- parse_response(RestClient.get(uri, default_headers), options.dup)
15
- rescue => e
16
- if $DEBUG
17
- raise "Error while sending a GET request #{uri}\n: #{e}"
18
- else
19
- raise e
20
- end
21
- end
22
- end
80
+ private
23
81
 
24
- def put(uri, doc = nil, options = {})
25
- opts = options.dup
26
- payload = payload_from_doc(doc, opts)
82
+ # Perform the RestClient request by removing the parse specific options, ensuring the
83
+ # payload is prepared, and sending the request ready to parse the response.
84
+ def execute(url, method, options = {}, payload = nil)
85
+ request, parser = prepare_and_split_options(url, method, options)
86
+ # Prepare the payload if it is provided
87
+ request[:payload] = payload_from_doc(payload, parser) if payload
27
88
  begin
28
- parse_response(RestClient.put(uri, payload, default_headers.merge(opts)), opts)
89
+ parse_response(RestClient::Request.execute(request), parser)
29
90
  rescue Exception => e
30
91
  if $DEBUG
31
- raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
92
+ raise "Error while sending a #{method.to_s.upcase} request #{uri}\noptions: #{opts.inspect}\n#{e}"
32
93
  else
33
94
  raise e
34
95
  end
35
96
  end
36
97
  end
37
98
 
38
- def post(uri, doc = nil, options = {})
39
- opts = options.dup
40
- payload = payload_from_doc(doc, opts)
41
- begin
42
- parse_response(RestClient.post(uri, payload, default_headers.merge(opts)), opts)
43
- rescue Exception => e
44
- if $DEBUG
45
- raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
99
+ # Prepare a two hashes, one for the request to the REST backend and a second
100
+ # for the JSON parser.
101
+ #
102
+ # Returns and array of request options and parser options.
103
+ #
104
+ def prepare_and_split_options(url, method, options)
105
+ request = {
106
+ :url => url,
107
+ :method => method,
108
+ :headers => default_headers.merge(options[:headers] || {})
109
+ }
110
+ parser = {
111
+ :raw => false
112
+ }
113
+ # Split the options
114
+ (options || {}).each do |k,v|
115
+ k = k.to_sym
116
+ next if k == :headers # already dealt with
117
+ if restclient_option_keys.include?(k)
118
+ request[k] = v
119
+ elsif header_option_keys.include?(k)
120
+ request[:headers][k] = v
46
121
  else
47
- raise e
122
+ parser[k] = v
48
123
  end
49
124
  end
125
+ [request, parser]
50
126
  end
51
127
 
52
- def delete(uri, options = {})
53
- parse_response(RestClient.delete(uri, default_headers), options.dup)
54
- end
55
-
56
- def copy(uri, destination, options = {})
57
- parse_response(RestClient::Request.execute( :method => :copy,
58
- :url => uri,
59
- :headers => default_headers.merge('Destination' => destination)
60
- ).to_s, options)
61
- end
62
-
63
- protected
64
-
65
128
  # Check if the provided doc is nil or special IO device or temp file. If not,
66
129
  # encode it into a string.
130
+ #
131
+ # The options supported are:
132
+ # * :raw TrueClass, if true the payload will not be altered.
133
+ #
67
134
  def payload_from_doc(doc, opts = {})
68
135
  (opts.delete(:raw) || doc.nil? || doc.is_a?(IO) || doc.is_a?(Tempfile)) ? doc : MultiJson.encode(doc)
69
136
  end
@@ -73,5 +140,16 @@ module CouchRest
73
140
  opts.delete(:raw) ? result : MultiJson.decode(result, opts.update(:max_nesting => false))
74
141
  end
75
142
 
143
+ # An array of all the options that should be passed through to restclient.
144
+ # Anything not in this list will be passed to the JSON parser.
145
+ def restclient_option_keys
146
+ [:method, :url, :payload, :headers, :timeout, :open_timeout,
147
+ :verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file]
148
+ end
149
+
150
+ def header_option_keys
151
+ [ :content_type, :accept ]
152
+ end
153
+
76
154
  end
77
155
  end
@@ -1,3 +1,3 @@
1
1
  module CouchRest
2
- VERSION = '1.1.0.pre3'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -25,7 +25,7 @@ describe CouchRest do
25
25
  @cr.info.class.should == Hash
26
26
  end
27
27
  end
28
-
28
+
29
29
  it "should restart" do
30
30
  @cr.restart!
31
31
  begin
@@ -303,7 +303,7 @@ describe CouchRest::Database do
303
303
  @db.fetch_attachment(@db.get('mydocwithattachment'), 'test.html').should == @attach
304
304
  end
305
305
  end
306
-
306
+
307
307
  describe "PUT attachment from file" do
308
308
  before(:each) do
309
309
  filename = FIXTURE_PATH + '/attachments/couchdb.png'
@@ -316,12 +316,11 @@ describe CouchRest::Database do
316
316
  r = @db.put_attachment({'_id' => 'attach-this'}, 'couchdb.png', image = @file.read, {:content_type => 'image/png'})
317
317
  r['ok'].should == true
318
318
  doc = @db.get("attach-this")
319
- attachment = @db.fetch_attachment(doc,"couchdb.png")
320
- if attachment.respond_to?(:net_http_res)
321
- attachment.net_http_res.body.should == image
322
- else
323
- attachment.should == image
324
- end
319
+ attachment = @db.fetch_attachment(doc, "couchdb.png")
320
+ (attachment == image).should be_true
321
+ #if attachment.respond_to?(:net_http_res)
322
+ # attachment.net_http_res.body.should == image
323
+ #end
325
324
  end
326
325
  end
327
326
 
@@ -33,7 +33,7 @@ describe CouchRest::Document do
33
33
  it "should respond to forwarded hash methods" do
34
34
  @doc = CouchRest::Document.new(:foo => 'bar')
35
35
  [:to_a, :==, :eql?, :keys, :values, :each, :reject, :reject!, :empty?,
36
- :clear, :merge, :merge!, :encode_json, :as_json, :to_json].each do |call|
36
+ :clear, :merge, :merge!, :encode_json, :as_json, :to_json, :frozen?].each do |call|
37
37
  @doc.should respond_to(call)
38
38
  end
39
39
  end
@@ -94,6 +94,17 @@ describe CouchRest::Document do
94
94
  end
95
95
  end
96
96
 
97
+ describe "#freeze" do
98
+ it "should freeze the attributes, but not actual model" do
99
+ klass = Class.new(CouchRest::Document)
100
+ klass.class_eval { attr_accessor :test_attr }
101
+ @doc = klass.new('foo' => 'bar')
102
+ @doc.freeze
103
+ lambda { @doc['foo'] = 'bar2' }.should raise_error(/frozen/)
104
+ lambda { @doc.test_attr = "bar3" }.should_not raise_error
105
+ end
106
+ end
107
+
97
108
 
98
109
  describe "#inspect" do
99
110
  it "should provide a string of keys and values of the Response" do
@@ -0,0 +1,204 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest::RestAPI do
4
+
5
+ describe "class methods" do
6
+
7
+ subject { CouchRest }
8
+
9
+ let(:request) { RestClient::Request }
10
+ let(:simple_response) { "{\"ok\":true}" }
11
+ let(:parser) { MultiJson }
12
+ let(:parser_opts) { {:max_nesting => false} }
13
+
14
+ it "should exist" do
15
+ should respond_to :get
16
+ should respond_to :put
17
+ should respond_to :post
18
+ should respond_to :copy
19
+ should respond_to :delete
20
+ end
21
+
22
+ it "should provide default headers" do
23
+ should respond_to :default_headers
24
+ CouchRest.default_headers.should be_a(Hash)
25
+ end
26
+
27
+
28
+ describe :get do
29
+ it "should send basic request" do
30
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers}
31
+ request.should_receive(:execute).with(req).and_return(simple_response)
32
+ parser.should_receive(:decode).with(simple_response, parser_opts)
33
+ CouchRest.get('foo')
34
+ end
35
+
36
+ it "should never modify options" do
37
+ options = {:timeout => 1000}
38
+ options.freeze
39
+ request.should_receive(:execute).and_return(simple_response)
40
+ parser.should_receive(:decode)
41
+ expect { CouchRest.get('foo', options) }.to_not raise_error
42
+ end
43
+
44
+
45
+ it "should accept 'content_type' header" do
46
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers.merge(:content_type => :foo)}
47
+ request.should_receive(:execute).with(req).and_return(simple_response)
48
+ parser.should_receive(:decode).with(simple_response, parser_opts)
49
+ CouchRest.get('foo', :content_type => :foo)
50
+ end
51
+
52
+ it "should accept 'accept' header" do
53
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers.merge(:accept => :foo)}
54
+ request.should_receive(:execute).with(req).and_return(simple_response)
55
+ parser.should_receive(:decode).with(simple_response, parser_opts)
56
+ CouchRest.get('foo', :accept => :foo)
57
+ end
58
+
59
+ it "should forward RestClient options" do
60
+ req = {:url => 'foo', :method => :get, :timeout => 1000, :headers => CouchRest.default_headers}
61
+ request.should_receive(:execute).with(req).and_return(simple_response)
62
+ parser.should_receive(:decode).with(simple_response, parser_opts)
63
+ CouchRest.get('foo', :timeout => 1000)
64
+ end
65
+
66
+ it "should forward parser options" do
67
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers}
68
+ request.should_receive(:execute).with(req).and_return(simple_response)
69
+ parser.should_receive(:decode).with(simple_response, parser_opts.merge(:random => 'foo'))
70
+ CouchRest.get('foo', :random => 'foo')
71
+ end
72
+
73
+ it "should accept raw option" do
74
+ req = {:url => 'foo', :method => :get, :headers => CouchRest.default_headers}
75
+ request.should_receive(:execute).with(req).and_return(simple_response)
76
+ parser.should_not_receive(:decode)
77
+ CouchRest.get('foo', :raw => true).should eql(simple_response)
78
+ end
79
+
80
+ it "should allow override of method (not that you'd want to!)" do
81
+ req = {:url => 'foo', :method => :fubar, :headers => CouchRest.default_headers}
82
+ request.should_receive(:execute).with(req).and_return(simple_response)
83
+ parser.should_receive(:decode).with(simple_response, parser_opts)
84
+ CouchRest.get('foo', :method => :fubar)
85
+ end
86
+
87
+ it "should allow override of url (not that you'd want to!)" do
88
+ req = {:url => 'foobardom', :method => :get, :headers => CouchRest.default_headers}
89
+ request.should_receive(:execute).with(req).and_return(simple_response)
90
+ parser.should_receive(:decode).with(simple_response, parser_opts)
91
+ CouchRest.get('foo', :url => 'foobardom')
92
+ end
93
+
94
+
95
+ it "should forward an exception if raised" do
96
+ request.should_receive(:execute).and_raise(RestClient::Exception)
97
+ expect { CouchRest.get('foo') }.to raise_error(RestClient::Exception)
98
+ end
99
+
100
+ end
101
+
102
+ describe :post do
103
+ it "should send basic request" do
104
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => 'data'}
105
+ request.should_receive(:execute).with(req).and_return(simple_response)
106
+ parser.should_receive(:encode).with('data').and_return('data')
107
+ parser.should_receive(:decode).with(simple_response, parser_opts)
108
+ CouchRest.post('foo', 'data')
109
+ end
110
+
111
+ it "should send basic request" do
112
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => 'data'}
113
+ request.should_receive(:execute).with(req).and_return(simple_response)
114
+ parser.should_receive(:encode).with('data').and_return('data')
115
+ parser.should_receive(:decode).with(simple_response, parser_opts)
116
+ CouchRest.post('foo', 'data')
117
+ end
118
+
119
+ it "should send raw request" do
120
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => 'data'}
121
+ request.should_receive(:execute).with(req).and_return(simple_response)
122
+ parser.should_not_receive(:encode)
123
+ parser.should_receive(:decode).with(simple_response, parser_opts)
124
+ CouchRest.post('foo', 'data', :raw => true)
125
+ end
126
+
127
+ it "should not encode nil request" do
128
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers}
129
+ request.should_receive(:execute).with(req).and_return(simple_response)
130
+ parser.should_not_receive(:encode)
131
+ parser.should_receive(:decode).with(simple_response, parser_opts)
132
+ CouchRest.post('foo', nil)
133
+ end
134
+
135
+ it "should send raw request automatically if file provided" do
136
+ f = File.open(FIXTURE_PATH + '/attachments/couchdb.png')
137
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => f}
138
+ request.should_receive(:execute).with(req).and_return(simple_response)
139
+ parser.should_not_receive(:encode)
140
+ parser.should_receive(:decode).with(simple_response, parser_opts)
141
+ CouchRest.post('foo', f)
142
+ f.close
143
+ end
144
+
145
+ it "should send raw request automatically if Tempfile provided" do
146
+ f = Tempfile.new('couchrest')
147
+ req = {:url => 'foo', :method => :post, :headers => CouchRest.default_headers, :payload => f}
148
+ request.should_receive(:execute).with(req).and_return(simple_response)
149
+ parser.should_not_receive(:encode)
150
+ parser.should_receive(:decode).with(simple_response, parser_opts)
151
+ CouchRest.post('foo', f)
152
+ f.close
153
+ end
154
+
155
+
156
+ end
157
+
158
+
159
+ describe :put do
160
+ # Only test basic as practically same as post
161
+ it "should send basic request" do
162
+ req = {:url => 'foo', :method => :put, :headers => CouchRest.default_headers, :payload => 'data'}
163
+ request.should_receive(:execute).with(req).and_return(simple_response)
164
+ parser.should_receive(:encode).with('data').and_return('data')
165
+ parser.should_receive(:decode).with(simple_response, parser_opts)
166
+ CouchRest.put('foo', 'data')
167
+ end
168
+
169
+ end
170
+
171
+ describe :delete do
172
+ it "should send basic request" do
173
+ req = {:url => 'foo', :method => :delete, :headers => CouchRest.default_headers}
174
+ request.should_receive(:execute).with(req).and_return(simple_response)
175
+ parser.should_receive(:decode).with(simple_response, parser_opts)
176
+ CouchRest.delete('foo')
177
+ end
178
+ end
179
+
180
+ describe :copy do
181
+ it "should send basic request" do
182
+ headers = CouchRest.default_headers.merge(
183
+ 'Destination' => 'fooobar'
184
+ )
185
+ req = {:url => 'foo', :method => :copy, :headers => headers}
186
+ request.should_receive(:execute).with(req).and_return(simple_response)
187
+ parser.should_receive(:decode).with(simple_response, parser_opts)
188
+ CouchRest.copy('foo', 'fooobar')
189
+ end
190
+
191
+ it "should never modify header options" do
192
+ options = {:headers => {:content_type => :foo}}
193
+ options.freeze
194
+ request.should_receive(:execute).and_return(simple_response)
195
+ parser.should_receive(:decode)
196
+ expect { CouchRest.copy('foo', 'foobar', options) }.to_not raise_error
197
+ end
198
+
199
+ end
200
+
201
+
202
+ end
203
+
204
+ end
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchrest
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: 6
5
- version: 1.1.0.pre3
4
+ prerelease:
5
+ version: 1.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - J. Chris Anderson
@@ -103,6 +103,7 @@ files:
103
103
  - history.txt
104
104
  - init.rb
105
105
  - lib/couchrest.rb
106
+ - lib/couchrest/attributes.rb
106
107
  - lib/couchrest/commands/generate.rb
107
108
  - lib/couchrest/commands/push.rb
108
109
  - lib/couchrest/database.rb
@@ -125,6 +126,7 @@ files:
125
126
  - spec/couchrest/document_spec.rb
126
127
  - spec/couchrest/helpers/pager_spec.rb
127
128
  - spec/couchrest/helpers/streamer_spec.rb
129
+ - spec/couchrest/rest_api_spec.rb
128
130
  - spec/couchrest/server_spec.rb
129
131
  - spec/fixtures/attachments/README
130
132
  - spec/fixtures/attachments/couchdb.png