couchrest 1.1.2 → 1.1.3

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.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.2
1
+ 1.1.3
data/couchrest.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
 
29
29
  s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
30
30
  s.add_dependency(%q<mime-types>, ["~> 1.15"])
31
- s.add_dependency(%q<multi_json>, ["~> 1.0.0"])
31
+ s.add_dependency(%q<multi_json>, ["~> 1.0"])
32
32
  s.add_development_dependency(%q<json>, ["~> 1.5.1"])
33
33
  s.add_development_dependency(%q<rspec>, "~> 2.6.0")
34
34
  end
@@ -28,7 +28,7 @@ books.keys.each do |book|
28
28
  while line = file.gets
29
29
  lines << line
30
30
  if lines.length > 10
31
- db.save({
31
+ db.save_doc({
32
32
  :title => title,
33
33
  :chunk => chunk,
34
34
  :text => lines.join('')
@@ -16,9 +16,9 @@ word_count = {
16
16
  }'
17
17
  }
18
18
 
19
- db.delete db.get("_design/word_count") rescue nil
19
+ db.delete_doc db.get("_design/word_count") rescue nil
20
20
 
21
- db.save({
21
+ db.save_doc({
22
22
  "_id" => "_design/word_count",
23
23
  :views => {
24
24
  :words => word_count
data/history.txt CHANGED
@@ -1,3 +1,15 @@
1
+ == 1.1.3 - 2012-07-31
2
+
3
+ * Minor changes
4
+ * Add support for HTTP HEAD requests (Tim Anglade)
5
+ * Make CouchRest#database! check if a db exists before creating it (Tim Anglade)
6
+ * Use _doc suffix in examples for delete and save (Mickael Riga)
7
+ * Database#view should not modify the params (@krishan)
8
+ * Fix replication with couchdb >= 1.1.0 (@erickt)
9
+ * Streamer protection against bad responses improved (@erickt)
10
+ * Support atomic bulk save requests with all_or_nothing CouchDB parameter (@matthiasjakel)
11
+ * Update multi_json dependency so we can use any 1.x version (@dgraham)
12
+
1
13
  == 1.1.2 - 2011-07-18
2
14
 
3
15
  * Minor changes
@@ -163,7 +163,7 @@ module CouchRest
163
163
  # missing ids, supply one from the uuid cache.
164
164
  #
165
165
  # If called with no arguments, bulk saves the cache of documents to be bulk saved.
166
- def bulk_save(docs = nil, use_uuids = true)
166
+ def bulk_save(docs = nil, use_uuids = true, all_or_nothing = false)
167
167
  if docs.nil?
168
168
  docs = @bulk_save_cache
169
169
  @bulk_save_cache = []
@@ -176,7 +176,11 @@ module CouchRest
176
176
  doc['_id'] = nextid if nextid
177
177
  end
178
178
  end
179
- CouchRest.post "#{@root}/_bulk_docs", {:docs => docs}
179
+ request_body = {:docs => docs}
180
+ if all_or_nothing
181
+ request_body[:all_or_nothing] = true
182
+ end
183
+ CouchRest.post "#{@root}/_bulk_docs", request_body
180
184
  end
181
185
  alias :bulk_delete :bulk_save
182
186
 
@@ -243,6 +247,7 @@ module CouchRest
243
247
  # Query a CouchDB view as defined by a <tt>_design</tt> document. Accepts
244
248
  # paramaters as described in http://wiki.apache.org/couchdb/HttpViewApi
245
249
  def view(name, params = {}, payload = {}, &block)
250
+ params = params.dup
246
251
  payload['keys'] = params.delete(:keys) if params[:keys]
247
252
  # Try recognising the name, otherwise assume already prepared
248
253
  view_path = name_to_view_path(name)
@@ -341,6 +346,7 @@ module CouchRest
341
346
  def replicate(other_db, continuous, options)
342
347
  raise ArgumentError, "must provide a CouchReset::Database" unless other_db.kind_of?(CouchRest::Database)
343
348
  raise ArgumentError, "must provide a target or source option" unless (options.key?(:target) || options.key?(:source))
349
+ doc_ids = options.delete(:doc_ids)
344
350
  payload = options
345
351
  if options.has_key?(:target)
346
352
  payload['source'] = other_db.root
@@ -348,7 +354,7 @@ module CouchRest
348
354
  payload['target'] = other_db.root
349
355
  end
350
356
  payload['continuous'] = continuous
351
- payload['doc_ids'] = options[:doc_ids] if options[:doc_ids]
357
+ payload['doc_ids'] = doc_ids if doc_ids
352
358
  CouchRest.post "#{@host}/_replicate", payload
353
359
  end
354
360
 
@@ -27,14 +27,19 @@ module CouchRest
27
27
 
28
28
  def open_pipe(cmd, &block)
29
29
  first = nil
30
+ prev = nil
30
31
  IO.popen(cmd) do |f|
31
32
  first = f.gets # discard header
32
33
  while line = f.gets
33
34
  row = parse_line(line)
34
35
  block.call row unless row.nil? # last line "}]" discarded
36
+ prev = line
35
37
  end
36
38
  end
37
- parse_first(first)
39
+
40
+ raise RestClient::ServerBrokeConnection if $? && $?.exitstatus != 0
41
+
42
+ parse_first(first, prev)
38
43
  end
39
44
 
40
45
  def parse_line line
@@ -44,14 +49,11 @@ module CouchRest
44
49
  end
45
50
  end
46
51
 
47
- def parse_first first
52
+ def parse_first first, last
48
53
  return nil unless first
49
- parts = first.split(',')
50
- parts.pop
51
- line = parts.join(',')
52
- MultiJson.decode("#{line}}")
53
- rescue
54
- nil
54
+ header = MultiJson.decode(last ? first + last : first)
55
+ header.delete("rows")
56
+ header
55
57
  end
56
58
 
57
59
  end
@@ -5,7 +5,7 @@ module CouchRest
5
5
  # The basic low-level interface for all REST requests to the database. Everything must pass
6
6
  # through here before it is sent to the server.
7
7
  #
8
- # Five types of REST requests are supported: get, put, post, delete, and copy.
8
+ # Six types of REST requests are supported: get, put, post, delete, copy and head.
9
9
  #
10
10
  # Requests that do not have a payload, get, delete and copy, accept the URI and options parameters,
11
11
  # where as put and post both expect a document as the second parameter.
@@ -69,6 +69,11 @@ module CouchRest
69
69
  execute(uri, :copy, opts)
70
70
  end
71
71
 
72
+ # Send a HEAD request.
73
+ def head(uri, options = {})
74
+ execute(uri, :head, options)
75
+ end
76
+
72
77
  # The default RestClient headers used in each request.
73
78
  def default_headers
74
79
  {
@@ -108,7 +113,8 @@ module CouchRest
108
113
  :headers => default_headers.merge(options[:headers] || {})
109
114
  }
110
115
  parser = {
111
- :raw => false
116
+ :raw => false,
117
+ :head => (method == :head)
112
118
  }
113
119
  # Split the options
114
120
  (options || {}).each do |k,v|
@@ -141,7 +147,7 @@ module CouchRest
141
147
 
142
148
  # Parse the response provided.
143
149
  def parse_response(result, opts = {})
144
- opts.delete(:raw) ? result : MultiJson.decode(result, opts.update(:max_nesting => false))
150
+ (opts.delete(:raw) || opts.delete(:head)) ? result : MultiJson.decode(result, opts.update(:max_nesting => false))
145
151
  end
146
152
 
147
153
  # An array of all the options that should be passed through to restclient.
@@ -55,8 +55,10 @@ module CouchRest
55
55
 
56
56
  # Creates the database if it doesn't exist
57
57
  def database!(name)
58
- create_db(name) rescue nil
58
+ CouchRest.head "#{@uri}/#{name}" # Check if the URL is valid
59
59
  database(name)
60
+ rescue RestClient::ResourceNotFound # Thrown if the HTTP HEAD fails
61
+ create_db(name)
60
62
  end
61
63
 
62
64
  # GET the welcome message
@@ -137,6 +137,12 @@ describe CouchRest::Database do
137
137
  rs = @db.view('first/test', :keys => ["another", "wild"])
138
138
  rs['rows'].length.should == 2
139
139
  end
140
+ it "should not modify given params" do
141
+ original_params = {:keys => ["another", "wild"]}
142
+ params = original_params.dup
143
+ rs = @db.view('first/test', params)
144
+ params.should == original_params
145
+ end
140
146
  it "should accept a block" do
141
147
  rows = []
142
148
  rs = @db.view('first/test', :include_docs => true) do |row|
@@ -246,6 +252,13 @@ describe CouchRest::Database do
246
252
  @db.bulk_save
247
253
  @db.get("bulk_cache_1")["val"].should == "test"
248
254
  end
255
+
256
+ it "should make an atomic write when all_or_nothing is set" do
257
+ docs = [{"_id" => "oneB", "wild" => "and random"}, {"_id" => "twoB", "mild" => "yet local"}]
258
+ CouchRest.should_receive(:post).with("#{COUCHHOST}/couchrest-test/_bulk_docs", {:all_or_nothing => true, :docs => docs})
259
+
260
+ @db.bulk_save(docs, false, true)
261
+ end
249
262
 
250
263
  it "should raise an error that is useful for recovery" do
251
264
  @r = @db.save_doc({"_id" => "taken", "field" => "stuff"})
@@ -25,18 +25,93 @@ describe CouchRest::Streamer do
25
25
 
26
26
  it "should GET each row in a view" do
27
27
  count = 0
28
- @streamer.get("#{@db.root}/_all_docs") do |row|
28
+ header = @streamer.get("#{@db.root}/_all_docs") do |row|
29
29
  count += 1
30
30
  end
31
31
  count.should == 1001
32
+ header.should == {"total_rows" => 1001, "offset" => 0}
32
33
  end
33
34
 
34
35
  it "should GET each row in a view with params" do
35
36
  count = 0
36
- @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=5") do |row|
37
+ header = @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=5") do |row|
37
38
  count += 1
38
39
  end
39
40
  count.should == 5
41
+ header.should == {"total_rows" => 1001, "offset" => 0}
42
+ end
43
+
44
+ it "should GET no rows in a view with limit=0" do
45
+ count = 0
46
+ header = @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
47
+ count += 1
48
+ end
49
+ count.should == 0
50
+ header.should == {"total_rows" => 1001, "offset" => 0}
51
+ end
52
+
53
+ it "should raise an exception receives malformed data" do
54
+ IO.stub(:popen) do |cmd, block|
55
+ class F
56
+ def initialize
57
+ @lines = [
58
+ '{"total_rows": 123, "offset": "0", "rows": [',
59
+ '{"foo": 1},',
60
+ '{"foo": 2},',
61
+ ]
62
+ end
63
+
64
+ def gets
65
+ @lines.shift
66
+ end
67
+ end
68
+
69
+ f = F.new
70
+ block.call f
71
+
72
+ IO.unstub(:popen)
73
+ IO.popen 'true' do; end
74
+ end
75
+
76
+ count = 0
77
+ expect do
78
+ @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
79
+ count += 1
80
+ end
81
+ end.should raise_error(MultiJson::DecodeError)
82
+ end
83
+
84
+ it "should raise an exception if the couch connection fails" do
85
+ IO.stub(:popen) do |cmd, block|
86
+ class F
87
+ def initialize
88
+ @lines = [
89
+ '{"total_rows": 123, "offset": "0", "rows": [',
90
+ '{"foo": 1},',
91
+ '{"foo": 2},',
92
+ ]
93
+ end
94
+
95
+ def gets
96
+ @lines.shift
97
+ end
98
+ end
99
+
100
+ block.call F.new
101
+
102
+ IO.unstub(:popen)
103
+ IO.popen 'false' do; end
104
+ end
105
+
106
+ count = 0
107
+
108
+ expect do
109
+ @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
110
+ count += 1
111
+ end
112
+ end.should raise_error(RestClient::ServerBrokeConnection)
113
+
114
+ count.should == 2
40
115
  end
41
116
 
42
117
  it "should POST for each row in a view" do
@@ -17,6 +17,7 @@ describe CouchRest::RestAPI do
17
17
  should respond_to :post
18
18
  should respond_to :copy
19
19
  should respond_to :delete
20
+ should respond_to :head
20
21
  end
21
22
 
22
23
  it "should provide default headers" do
@@ -206,6 +207,13 @@ describe CouchRest::RestAPI do
206
207
 
207
208
  end
208
209
 
210
+ describe :head do
211
+ it "should send basic request" do
212
+ req = {:url => 'foo', :method => :head, :headers => CouchRest.default_headers}
213
+ request.should_receive(:execute).with(req).and_return(simple_response)
214
+ CouchRest.head('foo')
215
+ end
216
+ end
209
217
 
210
218
  end
211
219
 
metadata CHANGED
@@ -1,15 +1,10 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: couchrest
3
- version: !ruby/object:Gem::Version
4
- hash: 23
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.3
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 1
9
- - 2
10
- version: 1.1.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - J. Chris Anderson
14
9
  - Matt Aimonetti
15
10
  - Marcos Tapajos
@@ -18,100 +13,98 @@ authors:
18
13
  autorequire:
19
14
  bindir: bin
20
15
  cert_chain: []
21
-
22
- date: 2011-07-23 00:00:00 +02:00
23
- default_executable:
24
- dependencies:
25
- - !ruby/object:Gem::Dependency
16
+ date: 2012-07-31 00:00:00.000000000 Z
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
26
19
  name: rest-client
27
- prerelease: false
28
- requirement: &id001 !ruby/object:Gem::Requirement
20
+ requirement: !ruby/object:Gem::Requirement
29
21
  none: false
30
- requirements:
22
+ requirements:
31
23
  - - ~>
32
- - !ruby/object:Gem::Version
33
- hash: 13
34
- segments:
35
- - 1
36
- - 6
37
- - 1
24
+ - !ruby/object:Gem::Version
38
25
  version: 1.6.1
39
26
  type: :runtime
40
- version_requirements: *id001
41
- - !ruby/object:Gem::Dependency
42
- name: mime-types
43
27
  prerelease: false
44
- requirement: &id002 !ruby/object:Gem::Requirement
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.6.1
34
+ - !ruby/object:Gem::Dependency
35
+ name: mime-types
36
+ requirement: !ruby/object:Gem::Requirement
45
37
  none: false
46
- requirements:
38
+ requirements:
47
39
  - - ~>
48
- - !ruby/object:Gem::Version
49
- hash: 17
50
- segments:
51
- - 1
52
- - 15
53
- version: "1.15"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.15'
54
42
  type: :runtime
55
- version_requirements: *id002
56
- - !ruby/object:Gem::Dependency
57
- name: multi_json
58
43
  prerelease: false
59
- requirement: &id003 !ruby/object:Gem::Requirement
44
+ version_requirements: !ruby/object:Gem::Requirement
60
45
  none: false
61
- requirements:
46
+ requirements:
62
47
  - - ~>
63
- - !ruby/object:Gem::Version
64
- hash: 23
65
- segments:
66
- - 1
67
- - 0
68
- - 0
69
- version: 1.0.0
48
+ - !ruby/object:Gem::Version
49
+ version: '1.15'
50
+ - !ruby/object:Gem::Dependency
51
+ name: multi_json
52
+ requirement: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: '1.0'
70
58
  type: :runtime
71
- version_requirements: *id003
72
- - !ruby/object:Gem::Dependency
73
- name: json
74
59
  prerelease: false
75
- requirement: &id004 !ruby/object:Gem::Requirement
60
+ version_requirements: !ruby/object:Gem::Requirement
76
61
  none: false
77
- requirements:
62
+ requirements:
78
63
  - - ~>
79
- - !ruby/object:Gem::Version
80
- hash: 1
81
- segments:
82
- - 1
83
- - 5
84
- - 1
64
+ - !ruby/object:Gem::Version
65
+ version: '1.0'
66
+ - !ruby/object:Gem::Dependency
67
+ name: json
68
+ requirement: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ~>
72
+ - !ruby/object:Gem::Version
85
73
  version: 1.5.1
86
74
  type: :development
87
- version_requirements: *id004
88
- - !ruby/object:Gem::Dependency
89
- name: rspec
90
75
  prerelease: false
91
- requirement: &id005 !ruby/object:Gem::Requirement
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ~>
80
+ - !ruby/object:Gem::Version
81
+ version: 1.5.1
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ requirement: !ruby/object:Gem::Requirement
92
85
  none: false
93
- requirements:
86
+ requirements:
94
87
  - - ~>
95
- - !ruby/object:Gem::Version
96
- hash: 23
97
- segments:
98
- - 2
99
- - 6
100
- - 0
88
+ - !ruby/object:Gem::Version
101
89
  version: 2.6.0
102
90
  type: :development
103
- version_requirements: *id005
104
- description: CouchRest provides a simple interface on top of CouchDB's RESTful HTTP API, as well as including some utility scripts for managing views and attachments.
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ~>
96
+ - !ruby/object:Gem::Version
97
+ version: 2.6.0
98
+ description: CouchRest provides a simple interface on top of CouchDB's RESTful HTTP
99
+ API, as well as including some utility scripts for managing views and attachments.
105
100
  email: jchris@apache.org
106
101
  executables: []
107
-
108
102
  extensions: []
109
-
110
- extra_rdoc_files:
103
+ extra_rdoc_files:
111
104
  - LICENSE
112
105
  - README.md
113
106
  - THANKS.md
114
- files:
107
+ files:
115
108
  - .gitignore
116
109
  - Gemfile
117
110
  - LICENSE
@@ -169,41 +162,47 @@ files:
169
162
  - spec/spec_helper.rb
170
163
  - utils/remap.rb
171
164
  - utils/subset.rb
172
- has_rdoc: true
173
165
  homepage: http://github.com/couchrest/couchrest
174
166
  licenses: []
175
-
176
167
  post_install_message:
177
- rdoc_options:
168
+ rdoc_options:
178
169
  - --charset=UTF-8
179
- require_paths:
170
+ require_paths:
180
171
  - lib
181
- required_ruby_version: !ruby/object:Gem::Requirement
172
+ required_ruby_version: !ruby/object:Gem::Requirement
182
173
  none: false
183
- requirements:
184
- - - ">="
185
- - !ruby/object:Gem::Version
186
- hash: 3
187
- segments:
188
- - 0
189
- version: "0"
190
- required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
179
  none: false
192
- requirements:
193
- - - ">"
194
- - !ruby/object:Gem::Version
195
- hash: 25
196
- segments:
197
- - 1
198
- - 3
199
- - 1
180
+ requirements:
181
+ - - ! '>'
182
+ - !ruby/object:Gem::Version
200
183
  version: 1.3.1
201
184
  requirements: []
202
-
203
185
  rubyforge_project:
204
- rubygems_version: 1.6.2
186
+ rubygems_version: 1.8.24
205
187
  signing_key:
206
188
  specification_version: 3
207
189
  summary: Lean and RESTful interface to CouchDB.
208
- test_files: []
209
-
190
+ test_files:
191
+ - spec/couchrest/couchrest_spec.rb
192
+ - spec/couchrest/database_spec.rb
193
+ - spec/couchrest/design_spec.rb
194
+ - spec/couchrest/document_spec.rb
195
+ - spec/couchrest/helpers/pager_spec.rb
196
+ - spec/couchrest/helpers/streamer_spec.rb
197
+ - spec/couchrest/rest_api_spec.rb
198
+ - spec/couchrest/server_spec.rb
199
+ - spec/fixtures/attachments/README
200
+ - spec/fixtures/attachments/couchdb.png
201
+ - spec/fixtures/attachments/test.html
202
+ - spec/fixtures/views/lib.js
203
+ - spec/fixtures/views/test_view/lib.js
204
+ - spec/fixtures/views/test_view/only-map.js
205
+ - spec/fixtures/views/test_view/test-map.js
206
+ - spec/fixtures/views/test_view/test-reduce.js
207
+ - spec/spec.opts
208
+ - spec/spec_helper.rb