lib/nested_set/base.rb in nested_set-1.6.7 vs lib/nested_set/base.rb in nested_set-1.6.8
- old
+ new
@@ -220,11 +220,11 @@
node[left_column_name] = indices[node_scope] += 1
# find
nodes_for_rebuild(node, node_scope).each{ |n| set_left_and_rights.call(n) }
# set right
node[right_column_name] = indices[node_scope] += 1
- node.save!
+ node.save(:validate => false)
end
# Find root node(s)
root_nodes_for_rebuild.each do |root_node|
node_scope = scope_for_rebuild(root_node)
@@ -476,10 +476,15 @@
# Find the first sibling to the right
def right_sibling
siblings.where("#{q_left} > ?", left).first
end
+ # Lock rows whose lfts and rgts are to be updated
+ def lock_check(cond=nil)
+ nested_set_scope.select(primary_key_column_name).where(cond).lock
+ end
+
# Shorthand method for finding the left sibling and moving to the left of it.
def move_left
move_to_left_of left_sibling
end
@@ -574,20 +579,23 @@
# Prunes a branch off of the tree, shifting all of the elements on the right
# back to the left so the counts still work.
def destroy_descendants
return if right.nil? || left.nil? || skip_before_destroy
- reload_nested_set
-
self.class.base_class.transaction do
- if acts_as_nested_set_options[:dependent] == :destroy
- descendants.each do |model|
- model.skip_before_destroy = true
- model.destroy
- end
- else
- nested_set_scope.delete_all(["#{q_left} > ? AND #{q_right} < ?", left, right])
+ lock_check(["#{quoted_right_column_name} > ?", right])
+ reload_nested_set
+ case destroy_method
+ when :delete_all then
+ nested_set_scope.delete_all(["#{q_left} > ? AND #{q_right} < ?", left, right])
+
+ else
+ descendants.each do |model|
+ model.skip_before_destroy = true
+ model.respond_to?(destroy_method) ? model.send(destroy_method) : raise(NoMethodError, "#{model} does not have a method #{destroy_method}")
+ end
+
end
# update lefts and rights for remaining nodes
diff = right - left + 1
nested_set_scope.update_all(
@@ -602,10 +610,15 @@
# Don't allow multiple calls to destroy to corrupt the set
self.skip_before_destroy = true
end
end
+ # just a shortcut
+ def destroy_method
+ acts_as_nested_set_options[:dependent]
+ end
+
# reload left, right, and parent
def reload_nested_set
reload(:select => "#{quoted_left_column_name}, " +
"#{quoted_right_column_name}, #{quoted_parent_column_name}")
end
@@ -648,14 +661,11 @@
# we have defined the boundaries of two non-overlapping intervals,
# so sorting puts both the intervals and their boundaries in order
a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
# select the rows in the model between a and d, and apply a lock
- self.class.base_class.find(:all,
- :select => primary_key_column_name,
- :conditions => ["#{quoted_left_column_name} >= :a and #{quoted_right_column_name} <= :d", {:a => a, :d => d}],
- :lock => true
- )
+ cond = ["#{quoted_left_column_name} >= :a and #{quoted_right_column_name} <= :d", { :a => a, :d => d }]
+ lock_check(cond)
new_parent = case position
when :child; target.id
when :root; nil
else target[parent_column_name]