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

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

Instance Method Summary collapse

Instance Method Details

#decendants_to_destroy_in_orderObject

Use reverse to delete from deepest child to parent in order to respect any possible foreign keys



39
40
41
# File 'lib/awesome_nested_set/model/prunable.rb', line 39

def decendants_to_destroy_in_order
  descendants.reverse
end

#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



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/awesome_nested_set/model/prunable.rb', line 43

def destroy_or_delete_descendants
  if acts_as_nested_set_options[:dependent] == :destroy
    decendants_to_destroy_in_order.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
      if Rails::VERSION::MAJOR < 5
        errors.add(:base, :"restrict_dependent_destroy.many", record: record)
        return false
      else
        errors.add(:base, :"restrict_dependent_destroy.has_many", record: record)
        throw :abort
      end
    end
    return true
   elsif acts_as_nested_set_options[:dependent] == :nullify
     descendants.update_all(parent_column_name => nil)
   else
    descendants.delete_all
  end
end

#diffObject



84
85
86
# File 'lib/awesome_nested_set/model/prunable.rb', line 84

def diff
  right - left + 1
end

#update_siblings(direction) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/awesome_nested_set/model/prunable.rb', line 76

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



71
72
73
74
# File 'lib/awesome_nested_set/model/prunable.rb', line 71

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