I have a Business model that :belongs_to Category
A sample hierarchy for categories:
- root
- Restaurants
- Sushi
- Pizza
- Chinese
- French
- Italian
- Restaurants
I am using acts_as_tree for Category hierarchy.
How can I find all Businesses under the Restaurants category?
If you want to get all descendants of a node in a tree-like hierarchy you have two options:
Use the classic
acts_as_tree, preload the selected category, start a cascade of queries to retrieve all the children, the grandchildren etc, until you get only leaves (nodes without further chidren). This approach is as good as it sounds.Use a more advanced tree representation, like nested set or closure tree. Under these representation you can get all descendants of a specific node with just one single query.
Then you get the collected categories and query in Businesses:
(technical explanation: nested set)
Under a nested set representation, each node has two indices, assigned in the following way: imagine that each node is a house with two windows, East and West, and the tree is like a bifurcating road where all children are more or less to the north of their parent. So you start to the east of the root house, and put a sequential number on the windows you meet. You never cross any road, you are only allowed to go around houses which has no further road to the north. At the end you’ll get again to the root house, and put a number on the west window.
The assigned numbers will have the following properties:
So, while inserting a new element in the tree is costly (it needs to update a number of indices), retrieving the whole descendance (all children, grandchildren, …) is quite easy, just take the nodes whose “east” and “west” numbers are between your chosen category’s east and west. You can actully do slightly better, but it doesn’t matter here.
A library like https://github.com/collectiveidea/awesome_nested_set will manage all this for you, and you only call
(technical explanation: closure tree)
This approach need an accessory table, where you store the transitive closure of the
child->parentrelationship (see http://en.wikipedia.org/wiki/Reflexive_transitive_closure#P_closures_of_binary_relations )The table will contain all pairs ancestor-descendant, so you can join in smart ways with that table to get almost any slicing of the hierarchy.
Again, a library such as https://github.com/mceachen/closure_tree will do the hard work for you, and you will be able to do