Renamed helpers to correspond to renamed Controller classes.
[merb_radiant.git] / radiant_extensions_plugins / plugins / acts_as_tree / lib / active_record / acts / .svn / text-base / tree.rb.svn-base
blob1f00e90a9ef24e13d439e0e7325f30e5355b9040
1 module ActiveRecord
2   module Acts
3     module Tree
4       def self.included(base)
5         base.extend(ClassMethods)
6       end
8       # Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
9       # association. This requires that you have a foreign key column, which by default is called +parent_id+.
10       #
11       #   class Category < ActiveRecord::Base
12       #     acts_as_tree :order => "name"
13       #   end
14       #
15       #   Example:
16       #   root
17       #    \_ child1
18       #         \_ subchild1
19       #         \_ subchild2
20       #
21       #   root      = Category.create("name" => "root")
22       #   child1    = root.children.create("name" => "child1")
23       #   subchild1 = child1.children.create("name" => "subchild1")
24       #
25       #   root.parent   # => nil
26       #   child1.parent # => root
27       #   root.children # => [child1]
28       #   root.children.first.children.first # => subchild1
29       #
30       # In addition to the parent and children associations, the following instance methods are added to the class
31       # after calling <tt>acts_as_tree</tt>:
32       # * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>)
33       # * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>)
34       # * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
35       # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>)
36       module ClassMethods
37         # Configuration options are:
38         #
39         # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
40         # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
41         # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
42         def acts_as_tree(options = {})
43           configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil }
44           configuration.update(options) if options.is_a?(Hash)
46           belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
47           has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy
49           class_eval <<-EOV
50             include ActiveRecord::Acts::Tree::InstanceMethods
52             def self.roots
53               find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
54             end
56             def self.root
57               find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
58             end
59           EOV
60         end
61       end
63       module InstanceMethods
64         # Returns list of ancestors, starting from parent until root.
65         #
66         #   subchild1.ancestors # => [child1, root]
67         def ancestors
68           node, nodes = self, []
69           nodes << node = node.parent while node.parent
70           nodes
71         end
73         # Returns the root node of the tree.
74         def root
75           node = self
76           node = node.parent while node.parent
77           node
78         end
80         # Returns all siblings of the current node.
81         #
82         #   subchild1.siblings # => [subchild2]
83         def siblings
84           self_and_siblings - [self]
85         end
87         # Returns all siblings and a reference to the current node.
88         #
89         #   subchild1.self_and_siblings # => [subchild1, subchild2]
90         def self_and_siblings
91           parent ? parent.children : self.class.roots
92         end
93       end
94     end
95   end
96 end