For our application we need a proper tree structure with Depth-First and Breadth-First searches, parent and child information. Also subtrees need to be exported to JSON. This gem will receive long-term support since we use it in our commercial long-term application.
Initially I thought of an embedded solution, but this will only be possible once MongoDB supports embedded collections, and even deep-embedded collections.
However this tree is right now on the top of our priority list, means we will put effort into this and release everything in this public gem, as soon as we implement and test it. It will be fully tested with Cucumber and RSpec.
An API Documentation can be found here:
I’ve made a screencast demonstrating our tree gem, where I go over the basic methods provided:
and a “Making Of” screencast, mostly about ruby metaprogramming
Install as Gem
gem install mongoid_tree
gem 'mongoid_tree', '0.3.3'
mongoid_tree can be included as a module
class Category include Mongoid::Document include Mongoid::Acts::Tree field :name validates_presence_of :name end
The following methods and fields are provided:
I use the _ :references_many, :stored_as => :array_ association Mongoid provides. Association names are fixed to .children and .parent at the moment, but I might make this optional later on.
# Appending a child node root_node.children << Category.new(:name => "node") # Inserting a child node before another node node_2.insert_before(Category.new(:name => "node_1")) # Inserting a child node after another node node_2.insert_before(Category.new(:name => "node_3"))
Accessing the Parent Object
node.parent # --> root_node
Just use the usual Association Methods provided by Mongoid. The entire subtree will also be deleted
node.delete #or node.destroy
You unhinge an entire subtree from it’s parent and move it to a new parent. The subtrees path information will automatically be rebuild.
This is probably your standard call if you want to loop to your tree. E.g. when building a menu. Calling Depth First will return the entire subtree including the node you called it on.
root_node.depth_first #or root_node.dfs
[ root_node, child_1, child_1.1, child_2, child_2.1, child_2.2 ]
This is a hardly used option, but hey, why not? Calling Breadth First will return the entire subtree including the node you called it on.
root_node.breadth_first #or root_node.bfs
[ root_node, child_1, child_2, child_1.1, child_2.1, child_2.2 ]
Jeweler Standard Text
Note on Patches/Pull Requests
- Fork the project.
- Make your feature addition or bug fix.
- Add tests for it. This is important so I don’t break it in a future version unintentionally.
- Commit, do not mess with rakefile, version, or history.
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
- Send me a pull request. Bonus points for topic branches.
Used Images are from Wikipedia
Copyright © 2010 Rainer Kuhn, LittleWebLab.com. See LICENSE for details.