Module: CollectiveIdea::Acts::NestedSet::Model::Prunable

Defined in:
lib/awesome_nested_set/model/prunable.rb

Instance Method Summary collapse

Instance Method Details

#destroy_descendantsObject

Prunes a branch off of the tree, shifting all of the elements on the right back to the left so the counts still work.



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
# File 'lib/awesome_nested_set/model/prunable.rb', line 9

def destroy_descendants
  return if right.nil? || left.nil? || skip_before_destroy

  in_tenacious_transaction do
    # Rescue from +ActiveRecord::RecordNotFound+ error as there may be a case
    # that an +object+ has already been destroyed by its parent, but objects that are
    # in memory are not aware about this.
    begin
      reload_nested_set
    rescue ActiveRecord::RecordNotFound
      self.skip_before_destroy = true
      return true
    end
    # select the rows in the model that extend past the deletion point and apply a lock
    nested_set_scope.right_of(left).select(primary_id).lock(true)

    return false unless destroy_or_delete_descendants

    # update lefts and rights for remaining nodes
    update_siblings_for_remaining_nodes

    # Reload is needed because children may have updated their parent (self) during deletion.
    reload

    # Don't allow multiple calls to destroy to corrupt the set
    self.skip_before_destroy = true
  end
end

#destroy_or_delete_descendantsObject



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/awesome_nested_set/model/prunable.rb', line 38

def destroy_or_delete_descendants
  if acts_as_nested_set_options[:dependent] == :destroy
    descendants.each do |model|
      model.skip_before_destroy = true
      model.destroy
    end
  elsif acts_as_nested_set_options[:dependent] == :restrict_with_exception
    raise ActiveRecord::DeleteRestrictionError.new(:children) unless leaf?
    return true
  elsif acts_as_nested_set_options[:dependent] == :restrict_with_error
    unless leaf?
      record = self.class.human_attribute_name(:children).downcase
      errors.add(:base, :"restrict_dependent_destroy.#{Rails::VERSION::MAJOR < 5 ? 'many' : 'has_many'}", record: record)
      return false
    end
    return true
   elsif acts_as_nested_set_options[:dependent] == :nullify
     descendants.update_all(parent_id: nil)
   else
    descendants.delete_all
  end
end

#diffObject



74
75
76
# File 'lib/awesome_nested_set/model/prunable.rb', line 74

def diff
  right - left + 1
end

#update_siblings(direction) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/awesome_nested_set/model/prunable.rb', line 66

def update_siblings(direction)
  full_column_name = send("quoted_#{direction}_column_full_name")
  column_name = send("quoted_#{direction}_column_name")

  nested_set_scope.where(["#{full_column_name} > ?", right]).
    update_all(["#{column_name} = (#{column_name} - ?)", diff])
end

#update_siblings_for_remaining_nodesObject



61
62
63
64
# File 'lib/awesome_nested_set/model/prunable.rb', line 61

def update_siblings_for_remaining_nodes
  update_siblings(:left)
  update_siblings(:right)
end