Fixed id_path calculation after editing parent_id, also fixed number of children calculation
Pull request Compare This branch is even with jaycode:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
migrations
test
LICENSE
README
Rakefile
TODO
init.rb
install.rb
uninstall.rb

README

In a nutshell
=============

Extend classic acts_as_tree, acts_as_nested_set to support:

* Fetching descendants with one sinqle query
* Fetching anscestors with one single query
* Fetching the root node of a node with one query 
* Store the level of each node
* Store the children count of each node
* Configure a "family" based on the level (depth) that can be different from the root node

Why?
===

The problem with classic acts_as_tree is that you need a large number of queries to retrieve the ascendants or descendants of a node. If you want the path of a node with a level of N , you need N – 1 queries. If you want all the children and grandchildren and so forth , you need to recurse at least N  times. This can become a pain if your tree is more than 3 or 4 levels. 
Acts as nested set offers functionality to retrieve all descendants of a node with a single query, but you can't do the same for ancestors which is very usefull for a number of things (i.e breadcrumbs) 

If your application offers a hierarchical based browsing, you'll probably need to query the tree all the time to create breadcrumbs or lists with subcategories. Classic examples are ecommerce applications, price comparison sites etc. 

Families:
=========

In ecommerce applications it's very common to have families of products or categories. For example:

Electronics
| -> Computers & Peripherals
| --> Storage
| ----> Hard Disks
| --------> SSD

The root node of SSD is Electronics but that's not the actually family of products because it covers a really big range. The actual family (depending on the application logic) can be Computers & Peripherals or Storage. If family_level is set to 1 for example, the family will be Computers & Peripherals.

Installing 
==========

Install the plugin: 
script/plugin install http://github.com/bandito/acts_as_tree_on_steroids.git

Usage
=====

Your model must have the following database tables:

* parent_id (lnteger)
* id_path (string)
* children_count (integer)
* level (integer)

Optionally you can enable family support by adding the following column.
* family_id (integer)

You should add indexes for id_path, parent_id and family_id (level and children_count will probably have a low cardinality , but you can index them anyway)

Then include the helper in your model.

class Category
	acts_as_tree_on_steroids :family_level => 1
end

How does it work
================

When a node is created or changes parent the id_path reflects the node path from the root to the node as a comma seperated value of ids. 
For example a really small tree would look like this

1
1,2
1,2,3
1,2,4
1,5
1,6
1,6,11
1,6,11,17
20
20,21
20,21,22
20,21,23
20,21,23,25

If we want to get the descendants of node with id_path 1,6 then we would query for "id_path like '1,6,%'" which would match 1,6,11 and 1,6,11,17. 
The database will use the index on id_path since it's not starting with a wildcard.

Likewise, if we wanted the ancestors of the node with id_path 1,6,11,17 we would just query for "id in (1,6,11,17)" to get them with a single query.

When to use it
==============

* You have a category tree that rarely changes but you are doing breadcrumbs and tree representations all the time. 
* You have to need to query for i.e products that belong to the current node and the descendant nodes

When not to use it
==================

* If your tree changes frequently then the overhead of the tree traverse can be a pain.
* You don't need to know the hierarchy of the node.