Permalink
Browse files

Merge remote-tracking branch 'ridsagrawal/master'

Conflicts:
	lib/ancestry/instance_methods.rb
  • Loading branch information...
2 parents cd268b6 + 94dba1c commit 5c90437974d0e8ca9ee19650b7e4b268d4805270 Stefan Henzen committed Jun 27, 2012
Showing with 32 additions and 6 deletions.
  1. +1 −0 README.rdoc
  2. +3 −3 lib/ancestry/class_methods.rb
  3. +10 −3 lib/ancestry/instance_methods.rb
  4. +18 −0 test/has_ancestry_test.rb
View
@@ -74,6 +74,7 @@ The has_ancestry methods supports the following options:
:destroy All children are destroyed as well (default)
:rootify The children of the destroyed node become root nodes
:restrict An AncestryException is raised if any children exist
+ :parentify The orphan subtree is added to the parent of the deleted node.If the deleted node is Root, then rootify the orphan subtree.
:cache_depth Cache the depth of each node in the 'ancestry_depth' column (default: false)
If you turn depth_caching on for an existing model:
- Migrate: add_column [table], :ancestry_depth, :integer, :default => 0
@@ -19,11 +19,11 @@ def scope_depth depth_options, depth
# Orphan strategy writer
def orphan_strategy= orphan_strategy
- # Check value of orphan strategy, only rootify, restrict or destroy is allowed
- if [:rootify, :restrict, :destroy].include? orphan_strategy
+ # Check value of orphan strategy, only rootify, adopt, restrict or destroy is allowed
+ if [:rootify, :adopt, :restrict, :destroy].include? orphan_strategy
class_variable_set :@@orphan_strategy, orphan_strategy
else
- raise Ancestry::AncestryException.new("Invalid orphan strategy, valid ones are :rootify, :restrict and :destroy.")
+ raise Ancestry::AncestryException.new("Invalid orphan strategy, valid ones are :rootify,:adopt, :restrict and :destroy.")
end
end
@@ -27,7 +27,7 @@ def update_descendants_with_new_ancestry
end
end
end
-
+
# Apply orphan strategy
def apply_orphan_strategy
# Skip this if callbacks are disabled
@@ -48,6 +48,14 @@ def apply_orphan_strategy
descendant.destroy
end
end
+ # ... make child elements of this node, child of its parent if orphan strategy is adopt
+ elsif self.base_class.orphan_strategy == :adopt
+ descendants.all.each do |descendant|
+ descendant.without_ancestry_callbacks do
+ new_ancestry = descendant.ancestor_ids.delete_if { |x| x == self.id }.join("/")
+ descendant.update_attribute descendant.class.ancestry_column, new_ancestry || nil
+ end
+ end
# ... throw an exception if it has children and orphan strategy is restrict
elsif self.base_class.orphan_strategy == :restrict
raise Ancestry::AncestryException.new('Cannot delete record because it has descendants.') unless is_childless?
@@ -158,7 +166,7 @@ def siblings
end
def sibling_ids
- siblings.all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym)
+ siblings.all(:select => self.base_class.primary_key).collect(&self.base_class.primary_key.to_sym)
end
def has_siblings?
@@ -219,7 +227,6 @@ def cast_primary_key(key)
def primary_key_type
@primary_key_type ||= column_for_attribute(self.class.primary_key).type
end
-
def unscoped_descendants
self.base_class.unscoped do
self.base_class.all(:conditions => descendant_conditions)
View
@@ -1,6 +1,7 @@
require "environment"
class HasAncestryTreeTest < ActiveSupport::TestCase
+
def test_default_ancestry_column
AncestryTestDatabase.with_model do |model|
assert_equal :ancestry, model.ancestry_column
@@ -302,6 +303,23 @@ def test_orphan_restrict_strategy
end
end
end
+
+ def test_orphan_adopt_strategy
+ AncestryTestDatabase.with_model do |model|
+ model.orphan_strategy = :adopt # set the orphan strategy as paerntify
+ n1 = model.create! #create a root node
+ n2 = model.create!(:parent => n1) #create child with parent=root
+ n3 = model.create!(:parent => n2) #create child with parent=n2, depth = 2
+ n4 = model.create!(:parent => n2) #create child with parent=n2, depth = 2
+ n5 = model.create!(:parent => n4) #create child with parent=n4, depth = 3
+ n2.destroy # delete a node with desecendants
+ assert_equal(model.find(n3.id).parent,n1, "orphan's not parentified" )
+ assert_equal(model.find(n5.id).ancestor_ids,[n1.id,n4.id], "ancestry integrity not maintained")
+ n1.destroy # delete a root node with desecendants
+ assert_equal(model.find(n3.id).parent_id,nil," Children of the deleted root not rootfied")
+ assert_equal(model.find(n5.id).ancestor_ids,[n4.id],"ancestry integrity not maintained")
+ end
+ end
def test_integrity_checking
AncestryTestDatabase.with_model :width => 3, :depth => 3 do |model, roots|

3 comments on commit 5c90437

Hi @StefanH ,
Thank you for the merge.The readme file is still showing the orphan strategy as 'parentify', it should be 'rootify'. I have changed the readme in my branch. Do I need to put another pull request for the readme to be rectified?

Collaborator

StefanH replied Jun 29, 2012

Hi, tnx for mentioning that, No need to bother with another pull request, I'll fix it.

Thank You.

Please sign in to comment.