Class: Copier

Inherits:
Object
  • Object
show all
Defined in:
lib/copier.rb

Instance Method Summary collapse

Constructor Details

#initialize(src_db, dst_db) ⇒ Copier

Returns a new instance of Copier.



4
5
6
# File 'lib/copier.rb', line 4

def initialize src_db, dst_db
  @src_db, @dst_db = src_db, dst_db
end

Instance Method Details

#copy(src, old_dst = nil) ⇒ Object

copy src_doc and all attachments, dst_doc is the current doc in the dst_db



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/copier.rb', line 9

def copy src, old_dst = nil

  # get source doc if src is a string (key)
  src_doc = src.is_a?(String) ? @src_db.get(src) :
  (src.is_a?(Hash) ? CouchRest::Document.new(src) : src)
  src_doc.database = @src_db # in case it's a hash, not a CouchRest::Document

  raise "document not found '#{src}'" if src_doc.nil?

  new_dst = src_doc.clone

  attachments_changed = false

  # if src has attachments, check whether they have changed or not
  if src_doc['_attachments']
    if (old_dst.nil? || old_dst["_attachments"] != src_doc['_attachments']) # attachments have changed
      attachments_changed = true
      # remove attachments from dst_doc - they are added back later
      new_dst.delete "_attachments"
    end
  end

  # set the rev to the previous rev or remove it if new
  old_dst ? (new_dst["_rev"] = old_dst["_rev"]) : (new_dst.delete "_rev")

  if attachments_changed
    begin
      # saving the doc removes all old attachments (if any)
      # using regular save
      @dst_db.save_doc(new_dst)
      # copy attachments one by one
      src_doc['_attachments'].keys.each {|file| copy_attachment(src_doc, new_dst, file)}

      # attachment order might not be retained - reload doc again to make sure
      reloaded_doc = @dst_db.get new_dst['_id']
      if (reloaded_doc['_attachments'].keys != src_doc['_attachments'].keys)
        puts "correcting attachment order..."
        ordered_attachments = src_doc['_attachments'].keys.inject({}) do |memo, key|
          memo[key] = reloaded_doc['_attachments'][key]
          memo
        end
        reloaded_doc['_attachments'] = ordered_attachments
        @dst_db.save_doc(reloaded_doc)
      end
    rescue RestClient::Conflict
      puts "ERROR: document version conflict, skipping..."
      return
    end
  else
    # use bulk save if attachments have not changed
    @dst_db.bulk_save_doc(new_dst)
  end
end