mm-tree

This is a tree structure for MongoMapper documents that support rational numbers for positioning. Read about rational numbers in tree structures here: arxiv.org/pdf/0806.3115v1.pdf

The reason for the changed implementation to use rational numbers is to be able to query a tree and get the tree structure by sorting on the rational number. It also makes it easy to query parts of a tree as well.

Rational numbers is even better than left/right trees, as you can remove parts of a tree or a node without reordering the entire tree. It is a bit more complicated, but there are some really good benefits.

<img src=“https://secure.travis-ci.org/leifcr/mm-tree.png?branch=master” alt=“Build Status” />

Installation

If you are using bundler, and want latest stable gem

gem 'mm-tree'

For latest edge version:

gem 'mm-tree', :git => 'http://github.com/leifcr/mm-tree.git'

Usage

Enable the tree functionality by adding the plugin on your model

class Category
  include MongoMapper::Document
  plugin  MongoMapper::Plugins::Tree
  key :name, String
end

Note: Rational numbers positioning is enabled by default!

This adds one embedded tree_info (non-changeable) and the following class attributes:

  • tree_parent_id_field overrides the field used for parent_id (default: parent_id)

  • tree_search_class expects a Class that is a MongoMapper::Document to be used for search (So you can have one collection with inherited models and trees for each model, not conflicting with each other)

  • tree_use_rational_numbers use rational numbers for sorting. set to false if you don’t want it.

  • tree_order controls the order if rational numbers aren’t used (format :field_name.), else it will sort by rational numbers.

If you want to use explicit tree_order, you *have to* set tree_use_rational_numbers to false.

Configuration Examples

Not using rational numbers, sorting by name, and using a different ID field.

class Category
  include MongoMapper::Document
  plugin  MongoMapper::Plugins::Tree
  self.tree_parent_id_field      = "my_super_parent_id"
  self.tree_use_rational_numbers = false
  self.tree_order                = :name.asc
  key :name, String
end

Using rational numbers, and using search classes to have inherited models in same collection but different trees:

class Shape
  include MongoMapper::Document
  plugin  MongoMapper::Plugins::Tree
  self.tree_search_class = Shape
  key :name, String
end
class Circle < Shape
  self.tree_search_class = Circle
end
class Square < Shape
  self.tree_search_class = Square
end

Using rational numbers, and using search classes to have inherited models in same collection and same tree:

class Shape
  include MongoMapper::Document
  plugin  MongoMapper::Plugins::Tree
  self.tree_search_class = Shape
  key :name, String
end
class Circle < Shape
end
class Square < Shape
end

Example for moving parents

To move a child node from one parent to another you can do either move to a specific rational number, or just set the parent.

Move using parent

node_1      = Category.create(:name => "Node 1")
node_1_1    = Category.create(:name => "Node 1.1", :parent => @node_1)
node_2      = Category.create(:name => "Node 2")
node_1_1.parent = node_2
node_1_1.save
node_1_1.parent.name # => "Node 2"

Move using rational values (nv/dv)

node_1      = Category.create(:name => "Node 1")
node_1_1    = Category.create(:name => "Node 1.1", :parent => @node_1)
node_2      = Category.create(:name => "Node 2")
node_2.set_position(node_1_1.tree_info.nv, node_1_1.tree_info.dv) # move to position of node_1_1
node_2.save
node_2.siblings.first.name # => "Node 1.1"
node_2.parent.name # => "Node 1"
# Node 2 is now in front of Node 1.1 as it has taken node 1.1's place.

Check test_order.rb, test_tree.rb and test_search_class.rb for more examples and details on usage.

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.

  • Send me a pull request, if you have features you like to see implemented.

Thanks

_Jakob Vidmar_ (For the original MongoMapper Tree) _Joel Junström_ (I based this tree on his refactoring of Jakobs MongoMapper Tree) _MongoMapper devels_ (John Nunemaker, Brandon Keepers & others)

Original ideas are Copyright Jakob Vidmar and Joel Junström. Please see their github repositories for details Copyright © 2012 Leif Ringstad. See LICENSE for details.