Class: Releaf::Content::Node::Copy

Inherits:
Object
  • Object
show all
Includes:
Service
Defined in:
app/services/releaf/content/node/copy.rb

Instance Method Summary collapse

Methods included from Service

#add_error_and_raise

Instance Method Details

#callObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'app/services/releaf/content/node/copy.rb', line 7

def call
  prevent_infinite_copy_loop
  begin
    new_node = nil
    node.class.transaction do
      new_node = make_copy
    end
  rescue ActiveRecord::RecordInvalid
    add_error_and_raise 'descendant invalid'
  else
    node.update_settings_timestamp
    new_node
  end
end

#duplicatable_associations(owner_class) ⇒ Object



71
72
73
74
75
# File 'app/services/releaf/content/node/copy.rb', line 71

def duplicatable_associations(owner_class)
  Releaf::ResourceBase.new(owner_class).associations.collect do |association|
    { association.name => duplicatable_associations(association.klass) }
  end
end

#duplicate_contentObject



51
52
53
54
55
56
57
58
59
# File 'app/services/releaf/content/node/copy.rb', line 51

def duplicate_content
  if node.content.present?
    new_content = duplicate_object(node.content)
    new_content.save!
    new_content
  else
    nil
  end
end

#duplicate_dragonfly_attachments(original, copy) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'app/services/releaf/content/node/copy.rb', line 77

def duplicate_dragonfly_attachments(original, copy)
  attachment_keys = original.dragonfly_attachments.keys
  return unless attachment_keys.present?

  # during the dup() call the copy object has its dragonfly_attachments property duplicated from the original.
  # here it gets set to nil to force its reinitialization on next access
  copy.instance_variable_set(:@dragonfly_attachments, nil)

  # all uids must be cleared in a separate loop before accessing any of the attachments
  # (accessing any of the accessors regenerates the dragonfly_attachments collection and loads all uids)
  attachment_keys.each { |accessor| copy.send("#{accessor}_uid=", nil) }

  # once all uids have been reset, each attachment may be reassigned from the original.
  # reassignment forces dragonfly to internally treat the new attachment as a copy
  attachment_keys.each do |accessor|
    attachment = original.send(accessor)

    if attachment.present?
      begin
        attachment.path  # verify that the file exists
      rescue Dragonfly::Job::Fetch::NotFound
        attachment = nil
      end
    end

    copy.send("#{accessor}=", attachment)
  end
end

#duplicate_object(object) ⇒ Object



61
62
63
64
65
# File 'app/services/releaf/content/node/copy.rb', line 61

def duplicate_object object
  object.deep_clone include: duplicatable_associations(object.class) do |original, copy|
    supplement_object_duplication(original, copy)
  end
end

#duplicate_underObject



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/services/releaf/content/node/copy.rb', line 37

def duplicate_under
  new_node = nil
  node.class.transaction do
    new_node = node.class.new
    new_node.assign_attributes_from(node)
    new_node.content_id = duplicate_content.try(:id)
    new_node.prevent_auto_update_settings_timestamp do
      Releaf::Content::Node::SaveUnderParent.call(node: new_node, parent_id: parent_id)
    end
  end

  new_node
end

#make_copyObject



27
28
29
30
31
32
33
34
35
# File 'app/services/releaf/content/node/copy.rb', line 27

def make_copy
  new_node = duplicate_under

  node.children.each do |child|
    self.class.new(node: child, parent_id: new_node.id).make_copy
  end

  new_node
end

#prevent_infinite_copy_loopObject



22
23
24
25
# File 'app/services/releaf/content/node/copy.rb', line 22

def prevent_infinite_copy_loop
  return if node.self_and_descendants.find_by_id(parent_id).blank?
  add_error_and_raise("source or descendant node can't be parent of new node")
end

#supplement_object_duplication(original, copy) ⇒ Object



67
68
69
# File 'app/services/releaf/content/node/copy.rb', line 67

def supplement_object_duplication(original, copy)
  duplicate_dragonfly_attachments(original, copy)
end