aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2005-09-09 08:01:44 +0000
committerDavid Heinemeier Hansson <david@loudthinking.com>2005-09-09 08:01:44 +0000
commitb0630673213ed2bee99883cb9197ddf6457a3fac (patch)
treec28f2571c88c42e07bf9548313cabe66c196d0a7 /activerecord
parentc8e0e10e28948bce93ea9f28524f917d9e0ea2da (diff)
downloadrails-b0630673213ed2bee99883cb9197ddf6457a3fac.tar.gz
rails-b0630673213ed2bee99883cb9197ddf6457a3fac.tar.bz2
rails-b0630673213ed2bee99883cb9197ddf6457a3fac.zip
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
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG2
-rw-r--r--activerecord/lib/active_record/acts/tree.rb38
-rw-r--r--activerecord/test/fixtures/mixins.yml12
-rw-r--r--activerecord/test/mixin_test.rb30
4 files changed, 69 insertions, 13 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index 10b562362e..e6d6c78de4 100644
--- a/activerecord/CHANGELOG
+++ b/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/
diff --git a/activerecord/lib/active_record/acts/tree.rb b/activerecord/lib/active_record/acts/tree.rb
index 2463a1209a..5fc7ddf41c 100644
--- a/activerecord/lib/active_record/acts/tree.rb
+++ b/activerecord/lib/active_record/acts/tree.rb
@@ -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 \ No newline at end of file
+end
diff --git a/activerecord/test/fixtures/mixins.yml b/activerecord/test/fixtures/mixins.yml
index 9f8e1ee8de..1d990c2e8e 100644
--- a/activerecord/test/fixtures/mixins.yml
+++ b/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
diff --git a/activerecord/test/mixin_test.rb b/activerecord/test/mixin_test.rb
index a6f759432f..dd29d94ab1 100644
--- a/activerecord/test/mixin_test.rb
+++ b/activerecord/test/mixin_test.rb
@@ -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