Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Acts As Ordered List copied to Github, with the added ability to set the scope (like acts_as_list)
Ruby
tag: v0.1.6

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
spec
.gitignore
.rvmrc
CHANGELOG
Gemfile
Gemfile.lock
Guardfile
LICENSE.txt
README.textile
Rakefile
VERSION
ordered_tree.gemspec

README.textile

ActsAsOrderedTree

v.1.2

                                 +----+-----------+----------+---------+
  node_1                         | id | parent_id | position | name    |
    \_ node_2                    +----+-----------+----------+---------+
    \_ node_3                    |  1 |         0 |        1 | Node_1  |
    |    \_ node_4               |  2 |         1 |        1 | Node_2  |
    |    \_ node_5               |  3 |         1 |        2 | Node_3  |
    |    |   \_ node_8           |  4 |         3 |        1 | Node_4  |
    |    |   \_ node_9           |  5 |         3 |        2 | Node_5  |
    |    \_ node_10              |  6 |         1 |        3 | Node_6  |
    |    \_ node_11              |  7 |         1 |        4 | Node_7  |
    \_ node_6                    |  8 |         5 |        1 | Node_8  |
    \_ node_7                    |  9 |         5 |        2 | Node_9  |
    |                            | 10 |         3 |        3 | Node_10 |
    |                            | 11 |         3 |        4 | Node_11 |
  node_12                        | 12 |         0 |        2 | Node_12 |
    \_ node_13                   | 13 |        12 |        1 | Node_13 |
    \_ node_14                   | 14 |        12 |        2 | Node_14 |
    |    \_ node_15              | 15 |        14 |        1 | Node_15 |
    |    \_ node_16              | 16 |        14 |        2 | Node_16 |
    |    |   \_ node_19          | 17 |        12 |        3 | Node_17 |
    |    |   \_ node_20          | 18 |        12 |        4 | Node_18 |
    |    \_ node_21              | 19 |        16 |        1 | Node_19 |
    |    \_ node_22              | 20 |        16 |        2 | Node_20 |
    \_ node_17                   | 21 |        14 |        3 | Node_21 |
    \_ node_18                   | 22 |        14 |        4 | Node_22 |
                                 +----+-----------+----------+---------+
class Person < ActiveRecord::Base
  ordered_tree :foreign_key => :parent_id,
               :order       => :position
end

class CreatePeople < ActiveRecord::Migration
  def self.up
    create_table :people do |t|
      t.column :parent_id , :integer ,:null => false ,:default => 0
      t.column :position  , :integer
    end
    add_index(:people, :parent_id)
  end
end

Which “in effect” sets up the following:

belongs_to :parent,
           :class_name  => Person,
           :foreign_key => :parent_id

has_many   :children,
           :class_name  => Person,
           :foreign_key => :parent_id,
           :order       => :position

Note: :parent_id and :position are default values for the foreign_key and order, respectively.

Overview

     Actions    Tree Methods                                List Method
 --------------------------------------------------------------------------------------------------
     Create
                To create a child object at a specific position,
                use one of the following:
                  Person.create(:parent_id => parent.id, :position => 2)
                  parent.children << Person.new(:position => 3)
                  parent.children.create(:position => 5)

                To create a new 'root', use:
                  Person.create(:position => 2)

                :position will default to the bottom of the parent's list
                :parent_id defaults to 0 (Class.roots)

     Read
                roots (class method)                        self_and_siblings

                root                                        siblings

                parent                                      position_in_list

                ancestors

                children

                descendants

     Update
                shift_to(parent = nil, position = nil)      move_above(sibling = nil)

                orphan                                      move_higher

                orphan_children                             move_lower

                parent_adopts_children                      move_to_top

                orphan_self_and_children                    move_to_bottom

                orphan_self_and_parent_adopts_children

     Destroy
                destroy (deletes all descendants)

                destroy_and_orphan_children

                destroy_and_parent_adopts_children

Setting the scope

If you want to have multiple trees in the same database (let’s say you want to have multiple sets of pages for the different tenants on your database), you should set a scope. A scope basically says: “work within this scope when possible”.

How does it work?

Let’s say I have a multi-tenant CMS app. I want each site to have their own Page tree. So Page uses ordered_tree :scope => :site so that when I do this:

@site_1 = Site.create :name => "First site"
@site_2 = Site.create :name => "Second site"
Page.create(:site => @site_1).position # returns 1
Page.create(:site => @site_2).position # returns 1
Page.create(:site => @site_2).position # returns 2
Page.create(:site => @site_1).position # returns 2

Warning: Page.roots will always return all the root pages (all pages with parent_id of 0). That’s because there’s no way to know which pages you want to see. That means, when you want to get a site’s root pages, go through the site: @site.pages.roots

Here are all the ways to define the scope:

Give a symbol without _id:

ordered_tree :scope => :site

ordered_tree will add _id to :site so it becomes: :site_id

Thus, you can also pass:

Give a symbol with _id

ordered_tree :scope => :site_id

Override the scope_condition method

For more complex stuff, in the model that has ordered_tree, define a method like this:

def scope_condition
  "site_id = #{site_id} AND user_login = '#{user_login}'"
end

Install

gem ‘ordered_tree’

Something went wrong with that request. Please try again.