Module: ActiveRecord::Acts::Tree::ClassMethods
- Defined in:
- lib/active_record/acts/tree.rb
Overview
Specify this acts_as
extension if you want to model a tree structure by providing a parent association and a children association. This requires that you have a foreign key column, which by default is called parent_id
.
class Category < ActiveRecord::Base
acts_as_tree :order => "name"
end
Example:
root
\_ child1
\_ subchild1
\_ subchild2
root = Category.create("name" => "root")
child1 = root.children.create("name" => "child1")
subchild1 = child1.children.create("name" => "subchild1")
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 calling acts_as_tree
:
-
siblings
- Returns all the children of the parent, excluding the current node ([subchild2]
when called onsubchild1
) -
self_and_siblings
- Returns all the children of the parent, including the current node ([subchild1, subchild2]
when called onsubchild1
) -
ancestors
- Returns all the ancestors of the current node ([child1, root]
when called onsubchild2
) -
root
- Returns the root of the current node (root
when called onsubchild2
) -
descendants
- Returns a flat list of the descendants of the current node ([child1, subchild1, subchild2]
when called onroot
)
Instance Method Summary collapse
-
#acts_as_tree(options = {}) ⇒ Object
Configuration options are:.
Instance Method Details
#acts_as_tree(options = {}) ⇒ Object
Configuration options are:
-
foreign_key
- specifies the column name to use for tracking of the tree (default:parent_id
) -
order
- makes it possible to sort the children according to this SQL snippet. -
counter_cache
- keeps a count in achildren_count
column if set totrue
(default:false
).
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/active_record/acts/tree.rb', line 43 def acts_as_tree( = {}) configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil, :dependent => :destroy, :touch => false } configuration.update() if .is_a?(Hash) # facebooker seems unhappy with :touch if configuration[:touch] belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache], :touch => configuration[:touch] else belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] end has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => configuration[:dependent] class_eval <<-EOV include ActiveRecord::Acts::Tree::InstanceMethods scope :roots, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}} after_save :update_level_cache after_update :update_parents_counter_cache def self.root roots.first end def self.childless nodes = [] find(:all).each do |node| nodes << node if node.children.empty? end nodes end validates_each "#{configuration[:foreign_key]}" do |record, attr, value| if value if record.id == value record.errors.add attr, "cannot be it's own id" elsif record.descendants.map {|c| c.id}.include?(value) record.errors.add attr, "cannot be a descendant's id" end end end EOV end |