couch-db 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cd7e0350e725a546206b7e282da8b3da2243aafe
4
+ data.tar.gz: 6ca15a89196b694b0da64031c0e71129587c3bcc
5
+ SHA512:
6
+ metadata.gz: e1623c824fc6bf0aaceb843036e75d37fe47a177bdda6e8c9eef3c2a9c952e28c39c561d7a223ec3dcdc22eb2ca5e25a65dd038cacd1f44ee73c5251a51a4eb9
7
+ data.tar.gz: 647f9b023c4c202f8f384a208156d890ac126bb5da51fd0adc5f5a73ccd148c0fbca2821902c682fc4744394da0c5294b912a204ee10cd082d70221958117c74
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.6
4
+ - 2.2.2
5
+ - 2.0.0
6
+ before_install: gem install bundler -v 1.10
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in couch-request.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Maarten Trompper
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # Ruby CouchDB
2
+ [![Build Status](https://travis-ci.org/digitalheir/ruby-couch-db.svg)](https://travis-ci.org/digitalheir/ruby-couch-db)
3
+ [![Code Climate](https://codeclimate.com/repos/557eed7de30ba02ffe010520/badges/11baa9055d509aedf45d/gpa.svg)](https://codeclimate.com/repos/557eed7de30ba02ffe010520/feed)
4
+ [![Test Coverage](https://codeclimate.com/repos/557eed7de30ba02ffe010520/badges/11baa9055d509aedf45d/coverage.svg)](https://codeclimate.com/repos/557eed7de30ba02ffe010520/coverage)
5
+
6
+ Ruby gem to connect to a CouchDB database in Ruby, focusing on bulk requests. Make sure to watch Tim Anglade's excellent talk **[CouchDB & Ruby: You're Doing It Wrong](https://www.youtube.com/watch?v=zEMfvCqVL4E)**.
7
+
8
+ <center>
9
+ <a href="http://www.youtube.com/watch?feature=player_embedded&v=zEMfvCqVL4E
10
+ " target="_blank"><img src="https://img.youtube.com/vi/zEMfvCqVL4E/0.jpg"
11
+ alt="CouchDB & Ruby: You're Doing It Wrong by Tim Anglade" width="240" height="180" border="10" /></a>
12
+ </center>
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'couch-db'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install couch-db
29
+
30
+ ## Usage
31
+
32
+ ```ruby
33
+
34
+ require 'couch'
35
+
36
+ # Subclass Couch::Server for application-specific logic
37
+ class MyCouch < Couch::Server
38
+ DB_NAME = 'my-db'
39
+
40
+ def initialize
41
+ super(
42
+ 'https://user.couchprovider.com/', # The library automatically detects whether to use SSL
43
+ {
44
+ name: 'user',
45
+ password: 'supersecretpassword' # May be nil for public databases
46
+ }
47
+ )
48
+ @queue = []
49
+ end
50
+
51
+ def add_to_queue(doc, max_array_length: 3)
52
+ @queue << doc
53
+ flushed = post_bulk_if_big_enough(DB_NAME, @queue, max_array_length: max_array_length)
54
+ puts "Added #{doc[:_id]} to queue. Flushed: #{flushed}"
55
+ end
56
+
57
+ def flush_queue
58
+ length = @queue.length
59
+ post_bulk_throttled(DB_NAME, @queue) do |res|
60
+ puts "Flushed bulk, response code #{res.code}"
61
+ end
62
+ length
63
+ end
64
+ end
65
+
66
+ #####################
67
+ # Script starts here
68
+ #####################
69
+
70
+ # Initialize couch interface
71
+ couch = MyCouch.new
72
+ couch.put("/#{MyCouch::DB_NAME}",'') # Create database
73
+
74
+ # Add some documents to our database, triggering a bulk post after every 3 docs
75
+ (1..11).each do |i|
76
+ couch.add_to_queue({_id: "document-#{i}"})
77
+ end
78
+
79
+ # Get single document.
80
+ puts couch.get_doc(
81
+ 'document-7',
82
+ {stale: 'ok'} # Pass URL parameters in a hash
83
+ )
84
+
85
+ # Flush remaining docs
86
+ l = couch.flush_queue
87
+ puts "Flushed remaining #{l} docs in queue"
88
+
89
+ # Access docs
90
+ couch.all_docs(MyCouch::DB_NAME, 4) do |slice|
91
+ puts "> Next #{slice.length} docs:"
92
+ slice.each do |doc|
93
+ puts doc
94
+ end
95
+ end
96
+
97
+ # Delete database
98
+ couch.delete("/#{MyCouch::DB_NAME}")
99
+
100
+ ```
101
+
102
+ ## Development
103
+
104
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
105
+
106
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
107
+
108
+ ## Contributing
109
+
110
+ Bug reports and pull requests are welcome on GitHub at https://github.com/digitalheir/ruby-couch-db. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
111
+
112
+
113
+ ## License
114
+
115
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
116
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'couch'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,39 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'couch/db/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'couch-db'
8
+ spec.version = Couch::DB::VERSION
9
+ spec.authors = ['Maarten Trompper']
10
+ spec.email = ['maartentrompper@gmail.com']
11
+
12
+ spec.required_ruby_version = '>= 2'
13
+
14
+ spec.summary = %q{Interface with a CouchDB database. Focuses on bulk requests.}
15
+ # spec.description = %q{Write a longer description or delete this line.}
16
+ spec.homepage = 'https://github.com/digitalheir/couch-request'
17
+ spec.license = 'MIT'
18
+
19
+ # # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
20
+ # # delete this section to allow pushing this gem to any host.
21
+ # if spec.respond_to?(:metadata)
22
+ # spec.metadata['allowed_push_host'] = "http://mygemserver.com"
23
+ # else
24
+ # raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
25
+ # end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
+ spec.bindir = 'exe'
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ['lib']
31
+
32
+ spec.add_development_dependency 'bundler', '~> 1'
33
+ spec.add_development_dependency 'rake', '~> 10.0'
34
+ spec.add_development_dependency 'rspec', '~> 2.4'
35
+ spec.add_development_dependency 'codeclimate-test-reporter'
36
+
37
+
38
+ spec.add_runtime_dependency 'json', '~> 1'
39
+ end
data/lib/couch.rb ADDED
@@ -0,0 +1,367 @@
1
+ require 'couch/db/version'
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'objspace'
5
+ require 'openssl'
6
+
7
+ class Hash
8
+ def include_symbol_or_string?(param)
9
+ if param.is_a? Symbol or param.is_a? String
10
+ include? param.to_sym or include? param.to_s
11
+ else
12
+ false
13
+ end
14
+ end
15
+ end
16
+
17
+ module Couch
18
+ module BasicRequest
19
+ def delete(uri, open_timeout: 5*30, read_timeout: 5*30, fail_silent: false)
20
+ req=Net::HTTP::Delete.new(uri)
21
+ req.basic_auth @options[:name], @options[:password]
22
+ request(req, open_timeout: open_timeout, read_timeout: read_timeout, fail_silent: fail_silent)
23
+ end
24
+
25
+ def head(uri, open_timeout: 5*30, read_timeout: 5*30, fail_silent: true)
26
+ req = Net::HTTP::Head.new(uri)
27
+ req.basic_auth @options[:name], @options[:password]
28
+ request(req, open_timeout: open_timeout, read_timeout: read_timeout, fail_silent: fail_silent)
29
+ end
30
+
31
+ def get(uri, open_timeout: 5*30, read_timeout: 5*30, fail_silent: false)
32
+ req = Net::HTTP::Get.new(uri)
33
+ req.basic_auth @options[:name], @options[:password]
34
+ request(req, open_timeout: open_timeout, read_timeout: read_timeout, fail_silent: fail_silent)
35
+ end
36
+
37
+ def put(uri, json, open_timeout: 5*30, read_timeout: 5*30, fail_silent: false)
38
+ posty_request(json, Net::HTTP::Put.new(uri), open_timeout: open_timeout, read_timeout: read_timeout, fail_silent: fail_silent)
39
+ end
40
+
41
+ def post(uri, json, open_timeout: 5*30, read_timeout: 5*30, fail_silent: false)
42
+ posty_request(json, Net::HTTP::Post.new(uri), open_timeout: open_timeout, read_timeout: read_timeout, fail_silent: fail_silent)
43
+ end
44
+
45
+ def posty_request(json, req, open_timeout: 5*30, read_timeout: 5*30, fail_silent: false)
46
+ req.basic_auth @options[:name], @options[:password]
47
+ req['Content-Type'] = 'application/json;charset=utf-8'
48
+ req.body = json
49
+ request(req, open_timeout: open_timeout, read_timeout: read_timeout, fail_silent: fail_silent)
50
+ end
51
+
52
+ def request(req, open_timeout: 5*30, read_timeout: 5*30, fail_silent: false)
53
+ res = Net::HTTP.start(@url.host, @url.port,
54
+ :use_ssl => @url.scheme =='https') do |http|
55
+ http.open_timeout = open_timeout
56
+ http.read_timeout = read_timeout
57
+ http.request(req)
58
+ end
59
+ unless fail_silent or res.kind_of?(Net::HTTPSuccess)
60
+ # puts "CouchDb responsed with error code #{res.code}"
61
+ handle_error(req, res)
62
+ end
63
+ res
64
+ end
65
+
66
+ def create_postfix(query_params, default='')
67
+ if query_params
68
+ params_a = []
69
+ query_params.each do |key, value|
70
+ params_a << "#{key}=#{value}"
71
+ end
72
+ postfix = "?#{params_a.join('&')}"
73
+ else
74
+ postfix = default
75
+ end
76
+ postfix
77
+ end
78
+
79
+ def handle_error(req, res)
80
+ raise RuntimeError.new("#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}")
81
+ end
82
+
83
+ module Get
84
+ # Returns parsed doc from database
85
+ def get_doc(database, id)
86
+ res = get("/#{database}/#{CGI.escape(id)}")
87
+ JSON.parse(res.body)
88
+ end
89
+
90
+ def get_attachment_str(db, id, attachment)
91
+ uri = URI::encode "/#{db}/#{id}/#{attachment}"
92
+ get(uri).body
93
+ end
94
+ end
95
+
96
+ module Head
97
+ # Returns revision for given document
98
+ def get_rev(database, id)
99
+ res = head("/#{database}/#{CGI.escape(id)}")
100
+ if res.code == '200'
101
+ res['etag'].gsub(/^"|"$/, '')
102
+ else
103
+ nil
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # Bulk requests; use methods from Couch::BasicRequest
110
+ module BulkRequest
111
+ module Get
112
+ # Returns an array of the full documents for given database, possibly filtered with given parameters.
113
+ # We recommend you use all_docs instead.
114
+ #
115
+ # Note that the 'include_docs' parameter must be set to true for this.
116
+ def get_all_docs(database, params)
117
+ unless params.include_symbol_or_string? :include_docs
118
+ params.merge!({:include_docs => true})
119
+ end
120
+ postfix = create_postfix(params)
121
+ uri = URI::encode "/#{database}/_all_docs#{postfix}"
122
+ res = get(uri)
123
+ append_docs(JSON.parse(res.body))
124
+ end
125
+
126
+
127
+ # If a block is given, performs the block for each +limit+-sized slice of _all_docs.
128
+ # If no block is given, returns all docs by appending +limit+-sized slices of _all_docs.
129
+ #
130
+ # This method assumes your docs don't have the high-value Unicode character \ufff0. If it does, then behaviour is undefined. The reason why we use the startkey parameter instead of skip is that startkey is faster.
131
+ def all_docs(db, limit=750, opts={}, &block)
132
+ all_docs = []
133
+ start_key = nil
134
+ loop do
135
+ opts = opts.merge({limit: limit})
136
+ if start_key
137
+ opts[:startkey]=start_key
138
+ end
139
+ docs = (lambda { |options| get_all_docs(db, options) }).call(opts)
140
+ if docs.length <= 0
141
+ break
142
+ else
143
+ if block
144
+ block.call(docs)
145
+ else
146
+ all_docs < docs
147
+ end
148
+ start_key ="\"#{docs.last['_id']}\\ufff0\""
149
+ end
150
+ end
151
+ all_docs.flatten
152
+ end
153
+
154
+ # Returns an array of all rows for given view.
155
+ #
156
+ # We recommend you use rows_for_view instead.
157
+ def get_rows_for_view(database, design_doc, view, query_params=nil)
158
+ postfix = create_postfix(query_params)
159
+ uri = URI::encode "/#{database}/_design/#{design_doc}/_view/#{view}#{postfix}"
160
+ res = get(uri)
161
+ JSON.parse(res.body.force_encoding('utf-8'))['rows']
162
+ end
163
+
164
+ # If a block is given, performs the block for each +limit+-sized slice of rows for the given view.
165
+ # If no block is given, returns all rows by appending +limit+-sized slices of the given view.
166
+ def rows_for_view(db, design_doc, view, limit=500, opts={}, &block)
167
+ get_all_views(lambda { |options| get_rows_for_view(db, design_doc, view, options) }, limit, opts, block)
168
+ end
169
+
170
+
171
+ # Returns an array of all ids in the database
172
+ def get_all_ids(database, params)
173
+ ids=[]
174
+ postfix = create_postfix(params)
175
+
176
+ uri = URI::encode "/#{database}/_all_docs#{postfix}"
177
+ res = get(uri)
178
+ result = JSON.parse(res.body)
179
+ result['rows'].each do |row|
180
+ if row['error']
181
+ puts "#{row['key']}: #{row['error']}"
182
+ puts "#{row['reason']}"
183
+ else
184
+ ids << row['id']
185
+ end
186
+ end
187
+ ids
188
+ end
189
+
190
+ # Returns an array of all ids in the database
191
+ def all_ids(db, limit=500, opts={}, &block)
192
+ all_docs = []
193
+ start_key = nil
194
+ loop do
195
+ opts = opts.merge({limit: limit})
196
+ if start_key
197
+ opts[:startkey]=start_key
198
+ end
199
+ docs = (lambda { |options| get_all_ids(db, options) }).call(opts)
200
+ if docs.length <= 0
201
+ break
202
+ else
203
+ if block
204
+ block.call(docs)
205
+ else
206
+ all_docs < docs
207
+ end
208
+ start_key ="\"#{docs.last}\\ufff0\""
209
+ end
210
+ end
211
+ all_docs.flatten
212
+ end
213
+
214
+ # Returns an array of the full documents for given view, possibly filtered with given parameters. Note that the 'include_docs' parameter must be set to true for this.
215
+ #
216
+ # Also consider using `docs_for_view`
217
+ def get_docs_for_view(db, design_doc, view, params={})
218
+ params.merge!({:include_docs => true})
219
+ rows = get_rows_for_view(db, design_doc, view, params)
220
+ docs = []
221
+ rows.each do |row|
222
+ docs << row['doc']
223
+ end
224
+ docs
225
+ end
226
+
227
+ # If a block is given, performs the block for each +limit+-sized slice of documents for the given view.
228
+ # If no block is given, returns all docs by appending +limit+-sized slices of the given view.
229
+ def docs_for_view(db, design_doc, view, limit=750, opts={}, &block)
230
+ get_all_views(lambda { |options| get_docs_for_view(db, design_doc, view, options) }, limit, opts, block)
231
+ end
232
+
233
+ private
234
+
235
+ def get_all_views(next_results, limit, opts, block)
236
+ all = []
237
+ offset = 0
238
+ loop do
239
+ opts = opts.merge({
240
+ limit: limit,
241
+ skip: offset,
242
+ })
243
+ docs = next_results.call(opts)
244
+ if docs.length <= 0
245
+ break
246
+ else
247
+ if block
248
+ block.call(docs)
249
+ else
250
+ all < docs
251
+ end
252
+ offset += limit
253
+ end
254
+ end
255
+ all.flatten
256
+ end
257
+
258
+ def append_docs(result)
259
+ docs = []
260
+ result['rows'].each do |row|
261
+ if row['error'] or !row['doc']
262
+ puts "Found row with error:\n#{row['key']}: #{row['error']}\n#{row['reason']}"
263
+ else
264
+ docs << row['doc']
265
+ end
266
+ end
267
+ docs
268
+ end
269
+ end
270
+
271
+ module Delete
272
+ def bulk_delete(database, docs)
273
+ docs.each do |doc|
274
+ doc[:_deleted]=true
275
+ end
276
+ json = {:docs => docs}.to_json
277
+ post("/#{database}/_bulk_docs", json)
278
+ end
279
+ end
280
+
281
+ module Post
282
+ # Flushes the given hashes to CouchDB
283
+ def post_bulk(database, docs)
284
+ body = {:docs => docs}.to_json #.force_encoding('utf-8')
285
+ post("/#{database}/_bulk_docs", body)
286
+ end
287
+
288
+ def post_bulk_throttled(db, docs, max_size_mb: 15, max_array_length: 300, &block)
289
+ # puts "Flushing #{docs.length} docs"
290
+ bulk = []
291
+ bytesize = 0
292
+ docs.each do |doc|
293
+ bulk << doc
294
+ # TODO: Note that this may be inexact; see documentation for ObjectSpace.memsize_of
295
+ bytesize += ObjectSpace.memsize_of doc
296
+ if bytesize/1024/1024 > max_size_mb or bulk.length >= max_array_length
297
+ handle_bulk_flush(bulk, db, block)
298
+ bytesize=0
299
+ end
300
+ end
301
+ if bulk.length > 0
302
+ handle_bulk_flush(bulk, db, block)
303
+ end
304
+ end
305
+
306
+
307
+ def post_bulk_if_big_enough(db, docs, flush_size_mb: 10, max_array_length: 300)
308
+ flush = (get_bytesize_array(docs) >= (flush_size_mb*1024*1024) or docs.length >= max_array_length)
309
+ if flush
310
+ post_bulk_throttled(db, docs)
311
+ docs.clear
312
+ end
313
+ flush
314
+ end
315
+
316
+ private
317
+
318
+ def get_bytesize_array(docs)
319
+ bytesize = 0
320
+ docs.each do |doc|
321
+ # TODO: Note that this may be inexact; see documentation for ObjectSpace.memsize_of
322
+ bytesize += ObjectSpace.memsize_of doc
323
+ end
324
+ bytesize
325
+ end
326
+
327
+ def handle_bulk_flush(bulk, db, block)
328
+ res = post_bulk(db, bulk)
329
+ error_count=0
330
+ if res.body
331
+ begin
332
+ JSON.parse(res.body).each do |d|
333
+ error_count+=1 if d['error']
334
+ end
335
+ end
336
+ end
337
+ if error_count > 0
338
+ puts "Bulk request completed with #{error_count} errors"
339
+ end
340
+ if block
341
+ block.call(res)
342
+ end
343
+ bulk.clear
344
+ end
345
+ end
346
+ end
347
+
348
+ class Server
349
+ def initialize(url, options)
350
+ if url.is_a? String
351
+ url = URI(url)
352
+ end
353
+ @url = url
354
+ @options = options
355
+ @options[:use_ssl] ||= true
356
+ end
357
+
358
+ include BasicRequest
359
+ include BasicRequest::Head
360
+ include BasicRequest::Get
361
+ include BulkRequest::Get
362
+ include BulkRequest::Delete
363
+ include BulkRequest::Post
364
+
365
+ private
366
+ end
367
+ end
@@ -0,0 +1,6 @@
1
+ module Couch
2
+ # noinspection ALL
3
+ module DB
4
+ VERSION = '0.9.0'
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: couch-db
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Maarten Trompper
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-06-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: codeclimate-test-reporter
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: json
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1'
83
+ description:
84
+ email:
85
+ - maartentrompper@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - CODE_OF_CONDUCT.md
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - bin/console
99
+ - bin/setup
100
+ - couch-request.gemspec
101
+ - lib/couch.rb
102
+ - lib/couch/db/version.rb
103
+ homepage: https://github.com/digitalheir/couch-request
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '2'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.4.7
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Interface with a CouchDB database. Focuses on bulk requests.
127
+ test_files: []