couchrest 1.1.0.pre3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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