Added the instance methods #root and #ancestors on acts_as_tree and fixed siblings to not include the current node #2142, #2140 [coffee2code]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2163 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
David Heinemeier Hansson 2005-09-09 08:01:44 +00:00
parent c8e0e10e28
commit b063067321
4 changed files with 69 additions and 13 deletions

View File

@ -1,5 +1,7 @@
*SVN*
* Added the instance methods #root and #ancestors on acts_as_tree and fixed siblings to not include the current node #2142, #2140 [coffee2code]
* Fixed that Active Record would call SHOW FIELDS twice (or more) for the same model when the cached results were available #1947 [sd@notso.net]
* Added log_level and use_silence parameter to ActiveRecord::Base.benchmark. The first controls at what level the benchmark statement will be logged (now as debug, instead of info) and the second that can be passed false to include all logging statements during the benchmark block/

View File

@ -16,16 +16,23 @@ module ActiveRecord
# Example :
# root
# \_ child1
# \_ sub-child1
# \_ subchild1
# \_ subchild2
#
# root = Category.create("name" => "root")
# child1 = root.children.create("name" => "child1")
# subchild1 = child1.children.create("name" => "subchild1")
# child1 = root.children.create("name" => "child1")
# subchild1 = child1.children.create("name" => "subchild1")
#
# root.parent # => nil
# root.parent # => nil
# child1.parent # => root
# root.children # => [child1]
# root.children.first.children.first # => subchild1
#
# In addition to the parent and children associations, the following instance methods are added to the class
# after specifying the act:
# * siblings: Return all the children of the parent excluding the current node ([ subchild2 ] when called from subchild1)
# * ancestors: Returns all the ancestors of the current node ([child1, root] when called from subchild2)
# * root: Returns the root of the current node (root when called from subchild2)
module ClassMethods
# Configuration options are:
#
@ -48,15 +55,26 @@ module ActiveRecord
end
END
# Returns list of ancestors, starting from parent until root.
#
# subchild1.ancestors # => [child1, root]
define_method(:ancestors) do
node, nodes = self, []
nodes << node = node.parent until not node.has_parent?
nodes
end
define_method(:root) do
node = self
node = node.parent until not node.has_parent?
node
end
define_method(:siblings) do
if parent
self.class.find(:all, :conditions => [ "#{configuration[:foreign_key]} = ?", parent.id ], :order => configuration[:order])
else
self.class.roots
end
( has_parent? ? parent.children : self.class.roots ) - [self]
end
end
end
end
end
end
end

View File

@ -2,7 +2,7 @@
tree_1:
id: 1001
type: TreeMixin
parent_id: 0
parent_id:
tree_2:
id: 1002
@ -18,6 +18,16 @@ tree_4:
id: 1004
type: TreeMixin
parent_id: 1001
tree2_1:
id: 1005
type: TreeMixin
parent_id:
tree3_1:
id: 1006
type: TreeMixin
parent_id:
# List mixins

View File

@ -214,6 +214,13 @@ class TreeTest < Test::Unit::TestCase
assert_equal mixins(:tree_4).children, []
end
def test_has_parent
assert_equal false, mixins(:tree_1).has_parent?
assert_equal true, mixins(:tree_2).has_parent?
assert_equal true, mixins(:tree_3).has_parent?
assert_equal true, mixins(:tree_4).has_parent?
end
def test_parent
assert_equal mixins(:tree_2).parent, mixins(:tree_1)
assert_equal mixins(:tree_2).parent, mixins(:tree_4).parent
@ -221,11 +228,14 @@ class TreeTest < Test::Unit::TestCase
end
def test_delete
assert_equal 4, TreeMixin.count
assert_equal 6, TreeMixin.count
mixins(:tree_1).destroy
assert_equal 2, TreeMixin.count
mixins(:tree2_1).destroy
mixins(:tree3_1).destroy
assert_equal 0, TreeMixin.count
end
def test_insert
@extra = mixins(:tree_1).children.create
@ -239,6 +249,22 @@ class TreeTest < Test::Unit::TestCase
assert mixins(:tree_1).children.include?(mixins(:tree_4))
end
def test_root
assert_equal mixins(:tree_1), TreeMixin.root
end
def test_roots
assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], TreeMixin.roots
end
def test_siblings
assert_equal [mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).siblings
assert_equal [mixins(:tree_4)], mixins(:tree_2).siblings
assert_equal [], mixins(:tree_3).siblings
assert_equal [mixins(:tree_2)], mixins(:tree_4).siblings
assert_equal [mixins(:tree_1), mixins(:tree3_1)], mixins(:tree2_1).siblings
assert_equal [mixins(:tree_1), mixins(:tree2_1)], mixins(:tree3_1).siblings
end
end
class TouchTest < Test::Unit::TestCase