I was looking for a tree structure for a tagging application and I decided to check out wether a solution different from
acts_as_tree was available.
I stumbled upon Closure_tree and I was sold: it’s really fast and supports lots of customisations and features.
The installation is straightforward:
- add the gem (
- add a
parent_idcolumn to the model of yours you want to behave like a tree
- create a migration to generate a TagHierarchy table to store the tree structure.
For all the nitty-gritty details, check out the installation doc.
The basics commands to create a node and its relatives are what you expect from ActiveRecord relationships:
parent = Tag.create(:name => 'Parent')
and a child:
child = parent.children.create(:name => 'Child')
But what really interested me, was the ability to create a hierarchy quickly and with only one call:
child = Tag.find_or_create_by_path(["grandparent", "parent", "child"])
Every tag of the chain will be created only if not already present.
And as a bonus, it supports Graphviz for rendering the trees.
The only feature it doesn’t have, is the support for multiple parents: it’d have been interesting to have it, but the author says pull requests are welcomed, so if the need arises, I may contribute to it. 😉
As for the speed, I didn’t need huge performances for my pet project, so it wasn’t a requirement, but it’s nice to know that it requires only one SELECT to get almost all the informations:
- Fetch your whole ancestor lineage in 1 SELECT.
- Grab all your descendants in 1 SELECT.
- Get all your siblings in 1 SELECT.
- Find a node by ancestry path in 1 SELECT.