Module: ActsAsTree::ClassMethods
- Defined in:
- lib/acts_as_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
include ActsAsTree
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, excludingthe current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>)
-
self_and_siblings
- Returns all the children of the parent,including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>)
-
ancestors
- Returns all the ancestors of the current node(<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
-
root
- Returns the root of the current node (root
when called on <tt>subchild2</tt>)
Class Method Summary collapse
-
.generations ⇒ Object
Returns a hash of all nodes grouped by their level in the tree structure.
Instance Method Summary collapse
-
#acts_as_tree(options = {}) ⇒ Object
Configuration options are:.
Class Method Details
.generations ⇒ Object
Returns a hash of all nodes grouped by their level in the tree structure.
Class.generations # => { 0=> [root1, root2], 1=> [root1child1, root1child2, root2child1, root2child2] }
131 132 133 |
# File 'lib/acts_as_tree.rb', line 131 def self.generations all.group_by{ |node| node.tree_level } end |
Instance Method Details
#acts_as_tree(options = {}) ⇒ Object
Configuration options are:
-
primary_key
- specifies the column name for relations(default: +id+)
-
foreign_key
- specifies the column name to use for trackingof the tree (default: +parent_id+)
-
order
- makes it possible to sort the children according tothis SQL snippet.
-
counter_cache
- keeps a count in achildren_count
columnif set to +true+ (default: +false+). Specify a custom column by passing a symbol or string.
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/acts_as_tree.rb', line 66 def acts_as_tree( = {}) configuration = { primary_key: "id", foreign_key: "parent_id", order: nil, counter_cache: nil, dependent: :destroy, touch: false } configuration.update() if .is_a?(Hash) if configuration[:counter_cache] == true configuration[:counter_cache] = :children_count end belongs_to_opts = { class_name: name, primary_key: configuration[:primary_key], foreign_key: configuration[:foreign_key], counter_cache: configuration[:counter_cache], touch: configuration[:touch], inverse_of: :children } belongs_to_opts[:optional] = true if ActiveRecord::VERSION::MAJOR >= 5 belongs_to :parent, belongs_to_opts if ActiveRecord::VERSION::MAJOR >= 4 has_many :children, lambda { order configuration[:order] }, class_name: name, primary_key: configuration[:primary_key], foreign_key: configuration[:foreign_key], dependent: configuration[:dependent], inverse_of: :parent else has_many :children, class_name: name, primary_key: configuration[:primary_key], foreign_key: configuration[:foreign_key], order: configuration[:order], dependent: configuration[:dependent], inverse_of: :parent end class_eval <<-EOV include ActsAsTree::InstanceMethods def self.default_tree_order order_option = #{configuration[:order].inspect} order(order_option) end def self.root self.roots.first end def self.roots where(:#{configuration[:foreign_key]} => nil).default_tree_order end EOV # Returns a hash of all nodes grouped by their level in the tree structure. # # Class.generations # => { 0=> [root1, root2], 1=> [root1child1, root1child2, root2child1, root2child2] } def self.generations all.group_by{ |node| node.tree_level } end if configuration[:counter_cache] after_update :update_parents_counter_cache def children_counter_cache_column reflect_on_association(:parent).counter_cache_column end def leaves where(children_counter_cache_column => 0).default_tree_order end else # Fallback to less efficient ways to find leaves. class_eval <<-EOV def self.leaves internal_ids = select(:#{configuration[:foreign_key]}).where(arel_table[:#{configuration[:foreign_key]}].not_eq(nil)) where("\#{connection.quote_column_name('#{configuration[:primary_key]}')} NOT IN (\#{internal_ids.to_sql})").default_tree_order end EOV end end |