Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added the instance methods #root and #ancestors on acts_as_tree and f…

…ixed 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
  • Loading branch information...
commit b0630673213ed2bee99883cb9197ddf6457a3fac 1 parent c8e0e10
@dhh dhh authored
View
2  activerecord/CHANGELOG
@@ -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
38 activerecord/lib/active_record/acts/tree.rb
@@ -16,16 +16,23 @@ def self.append_features(base)
# 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 @@ def self.root
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
View
12 activerecord/test/fixtures/mixins.yml
@@ -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
30 activerecord/test/mixin_test.rb
@@ -214,6 +214,13 @@ def test_children
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 @@ def test_parent
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 @@ def test_insert
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
Please sign in to comment.
Something went wrong with that request. Please try again.