Skip to content

Commit

Permalink
Merge remote-tracking branch 'ridsagrawal/master'
Browse files Browse the repository at this point in the history
Conflicts:
	lib/ancestry/instance_methods.rb
  • Loading branch information
Stefan Henzen committed Jun 27, 2012
2 parents cd268b6 + 94dba1c commit 5c90437
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.rdoc
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions lib/ancestry/class_methods.rb
Expand Up @@ -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

Expand Down
13 changes: 10 additions & 3 deletions lib/ancestry/instance_methods.rb
Expand Up @@ -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
Expand All @@ -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?
Expand Down Expand Up @@ -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?
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions test/has_ancestry_test.rb
@@ -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
Expand Down Expand Up @@ -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|
Expand Down

0 comments on commit 5c90437

Please sign in to comment.