chill 5 → 6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/library/chill.rb +125 -10
  2. metadata +9 -9
@@ -57,10 +57,35 @@ module ChillDB
57
57
  return ChillDB::Document.new(@@database, hash).commit!
58
58
  end
59
59
 
60
+ # commit takes an array of documents, and does a bulk commit to the server (one single request)
61
+ # using a bulk commit is faster than calling commit! on each individual document object
62
+ def commit! *args
63
+ list(args.flatten).commit!
64
+ end
65
+
66
+ def delete! *args
67
+ list(args.flatten).delete!
68
+ end
69
+
70
+ # turn an array of documents in to a ChillDB::List
71
+ def list array = []
72
+ list = ChillDB::List.from_array array
73
+ list.database = @@database
74
+ return list
75
+ end
76
+
77
+ # all docs!
78
+ def everything
79
+ list = ChillDB::List.load(JSON.parse(@@database.http('_all_docs?include_docs=true').get.body))
80
+ list.database = @@database
81
+ return list
82
+ end
83
+
84
+ # open a resource to the server for a particular document, which you can get, post, etc to. For internal use.
60
85
  def open *args
61
86
  headers = { accept: '*/*' }
62
87
  headers.merge! args.pop if args.last.respond_to? :to_hash
63
- @@database.http(args.map { |i| URI.escape(i, /[^a-z0-9_.-]/i) }.join('/'), headers)
88
+ @@database.http(args.map { |item| URI.escape(item, /[^a-z0-9_.-]/i) }.join('/'), headers)
64
89
  end
65
90
  end
66
91
 
@@ -86,6 +111,17 @@ class ChillDB::Database
86
111
  return self
87
112
  end
88
113
 
114
+ # get info about database
115
+ def info
116
+ response = http('').get()
117
+ IndifferentHash.new.replace(JSON.parse response.body)
118
+ end
119
+
120
+ # pretty output for debugging things :)
121
+ def inspect
122
+ "#<ChillDB::Database: #{info.inspect} >"
123
+ end
124
+
89
125
  #def revs_limit; http('_revs_limit').get.body.to_i; end
90
126
  #def revs_limit=(v); http('_revs_limit').put(v.to_s); end
91
127
 
@@ -204,6 +240,7 @@ class ChillDB::Document < ChillDB::IndifferentHash
204
240
  # returns self, or if there's a more specific subclass, a subclassed version of Document
205
241
  def load lookup_revision = nil
206
242
  url = URI(URI.escape self['_id'])
243
+ lookup_revision ||= self['_rev']
207
244
  url.query = "rev=#{lookup_revision}" if lookup_revision
208
245
  response = @database.http(url).get
209
246
  return self if response.code == 404 # we can create it later
@@ -215,6 +252,7 @@ class ChillDB::Document < ChillDB::IndifferentHash
215
252
 
216
253
  # stores updates (or newly existingness) of document to origin database
217
254
  def commit!
255
+ return delete! if self['_deleted'] # just delete if we're marked for deletion
218
256
  json = JSON.generate(self)
219
257
  response = @database.http(URI.escape self['_id']).put(json);
220
258
  raise response.body unless (200..299).include? response.code
@@ -225,11 +263,17 @@ class ChillDB::Document < ChillDB::IndifferentHash
225
263
  return self
226
264
  end
227
265
 
228
- # delete this jerk
266
+ # mark this jerk for deletion! (useful for bulk commit)
267
+ def delete
268
+ self.replace('_id'=> self['_id'], '_rev'=> self['_rev'], '_deleted'=> true)
269
+ end
270
+
271
+ # delete this jerk immediately
229
272
  def delete!
230
273
  response = @database.http(URI.escape self['_id']).delete()
231
274
  response = ChillDB::IndifferentHash.new.replace JSON.parse(response.body)
232
275
  raise "Couldn't delete #{self._id}: #{response.error} - #{response.reason}" if response['error']
276
+ delete # make our contents be deleted
233
277
  return response
234
278
  end
235
279
 
@@ -249,6 +293,11 @@ class ChillDB::Document < ChillDB::IndifferentHash
249
293
  def to_param
250
294
  self['_id']
251
295
  end
296
+
297
+ # loose equality check
298
+ def == other_doc
299
+ other.is_a?(self.class) and (self['_id'] == other['_id']) and (self['_rev'] == other['_rev'])
300
+ end
252
301
  end
253
302
 
254
303
 
@@ -273,6 +322,14 @@ class ChillDB::List < Array
273
322
  return new_list
274
323
  end
275
324
 
325
+ # to make a list from a simple array (not a couchdb response...)
326
+ def self.from_array array
327
+ new_list = self.new
328
+ new_list.replace array.map do |item|
329
+ { 'id'=> item['_id'], 'key'=> item['_id'], 'value'=> item, 'doc'=> item }
330
+ end
331
+ end
332
+
276
333
  # store rows nicely in mah belleh
277
334
  def rows=(arr)
278
335
  self.replace(arr.map { |item|
@@ -342,21 +399,60 @@ class ChillDB::List < Array
342
399
  return hash
343
400
  end
344
401
 
402
+ # commit takes an array of documents, and does a bulk commit to the server (one single request)
403
+ # using a bulk commit is faster than calling commit! on each individual document object
404
+ def commit!
405
+ commit_documents! convert
406
+ end
407
+ alias_method :commit_all!, :commit!
408
+
345
409
  # remove all the documents in this list from the database
346
- def delete_all!
410
+ def delete!
411
+ # check all the entries have a _rev - if they don't they cannot be deleted!
347
412
  each do |item|
348
- raise "Some (all?) items in list do not contain _rev properties in their values" unless item['value']['_rev']
413
+ rev = item['value']['_rev'] || item['value']['rev'] || item['doc']['_rev']
414
+ raise "Some (all?) items in list do not contain _rev properties in their values" unless rev
349
415
  end
350
416
 
351
- request = { docs: map { |item|
352
- { _id: item['value']['_id'] || item['id'], _rev: item['value']['_rev'], _deleted: true }
353
- } }
417
+ # mark all documents for deletion and commit the order!
418
+ commit_documents! convert.map { |item| item.delete }
419
+ end
420
+
421
+ alias_method :delete_all!, :delete!
422
+
423
+ private
424
+ # get the list, with any non-ChillDB::Document's converted in to those
425
+ def convert
426
+ map do |item|
427
+ document = item['doc'] || item['value']
428
+ if document.is_a? ChillDB::Document
429
+ document
430
+ elsif document.respond_to? :to_hash
431
+ document['_rev'] ||= item['value']['_rev'] || item['value']['rev'] || item['doc']['_rev']
432
+ document = ChillDB::Document.new(@database, document.to_hash)
433
+ else
434
+ raise "Cannot convert #{document.inspect}"
435
+ end
436
+ end
437
+ end
438
+
439
+ # commit an array of documents to the server
440
+ def commit_documents! documents
441
+ response = @database.http('_bulk_docs').post(JSON.generate(docs: documents.to_a))
442
+ raise response.body unless (200..299).include? response.code
443
+ json = JSON.parse(response.body)
444
+ errors = []
354
445
 
355
- response = JSON.parse @database.http("_bulk_docs").post(request.to_json)
356
- raise "Error: #{response['error']} - #{response['reason']}" if response.is_a? Hash and response['error']
446
+ documents.each_index do |index|
447
+ self[index]['id'] = json[index]['id']
448
+ self[index]['value']['rev'] = json[index]['rev'] if json[index]['rev']
449
+ errors.push [self[index], json[index]] if json[index]['error']
450
+ end
357
451
 
358
- return ChillDB::IndifferentHash.new.replace response
452
+ raise errors unless errors.empty?
453
+ return self
359
454
  end
455
+
360
456
  end
361
457
 
362
458
 
@@ -437,3 +533,22 @@ end
437
533
 
438
534
 
439
535
 
536
+
537
+ class ChillDB::BulkUpdateErrors < StandardError
538
+ attr_accessor :failures
539
+
540
+ def initialize *args
541
+ @failures = args.pop
542
+ super(*args)
543
+ end
544
+
545
+ def inspect
546
+ "ChillDB::BulkUpdateError:\n" + @failures.map { |failure|
547
+ document, error = failure
548
+ " '#{document['_id']}': #{error['reason']}"
549
+ }.join('\n')
550
+ end
551
+ end
552
+
553
+
554
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chill
3
3
  version: !ruby/object:Gem::Version
4
- version: '5'
4
+ version: '6'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-31 00:00:00.000000000Z
12
+ date: 2012-04-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json
16
- requirement: &70177568025240 !ruby/object:Gem::Requirement
16
+ requirement: &70131867175840 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 1.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70177568025240
24
+ version_requirements: *70131867175840
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rest-client
27
- requirement: &70177568024660 !ruby/object:Gem::Requirement
27
+ requirement: &70131867175340 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.6.7
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70177568024660
35
+ version_requirements: *70131867175340
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: uuid
38
- requirement: &70177568024180 !ruby/object:Gem::Requirement
38
+ requirement: &70131867174860 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: 2.3.4
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70177568024180
46
+ version_requirements: *70131867174860
47
47
  description: A little library to talk to a couchdb. I made it skinny, because couchdb
48
48
  is very simple. I think that's a good thing.
49
49
  email: a@creativepony.com
@@ -72,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
72
  version: '0'
73
73
  requirements: []
74
74
  rubyforge_project:
75
- rubygems_version: 1.8.10
75
+ rubygems_version: 1.8.11
76
76
  signing_key:
77
77
  specification_version: 3
78
78
  summary: A tiny plug to hook ruby in to couchdb