mongoid_tree

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.

Documentation

An API Documentation can be found here:

http://rubydoc.info/gems/mongoid_tree/

Screencasts

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

Installation

Install as Gem gem install mongoid_tree

via Gemfile gem 'mongoid_tree', '0.3.3'

Usage

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:

Adding Children

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

Deleting Subtrees

Just use the usual Association Methods provided by Mongoid. The entire subtree will also be deleted


node.delete
#or
node.destroy

Moving Subtrees

You unhinge an entire subtree from it’s parent and move it to a new parent. The subtrees path information will automatically be rebuild.


node4.move_to(node_1)

Depth First

File:Depth-first-tree.svg

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</p>
<p>#returns
[ root_node, child_1, child_1.1, child_2, child_2.1, child_2.2 ]

Breadth First

File:Breadth-first-tree.svg

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</p>
<p>#returns
[ 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.

Copyright

Used Images are from Wikipedia

Copyright © 2010 Rainer Kuhn, LittleWebLab.com. See LICENSE for details.