<commit_before>= Closure Tree

Closure Tree is a mostly-API-compatible replacement for the
acts_as_tree and awesome_nested_set gems, but with much better
mutation performance thanks to the Closure Tree storage algorithm.

See {<NAME>}[http://karwin.blogspot.com/]'s excellent
{Models for hierarchical data presentation}[http://www.slideshare.net/billkarwin/models-for-hierarchical-data]
for a description of different tree storage algorithms.

== Setup

Note that closure_tree is being developed for Rails 3.1.0.rc1

1.  Add this to your Gemfile: <code>gem 'closure_tree'</code>

2.  Run <code>bundle install</code>

3.  Add <code>acts_as_tree</code> to your hierarchical model(s).

4.  Add a migration to add a <code>parent_id</code> column to the model you want to act_as_tree.

    Note that if the column is null, the tag will be considered a root node.

      class AddParentIdToTag < ActiveRecord::Migration
        def change
          add_column :tag, :parent_id, :integer
        end
      end

5.  Add a database migration to store the hierarchy for your model. By
    convention the table name will be the model's table name, followed by
    "_hierarchy". Note that by calling <code>acts_as_tree</code>, a "virtual model" (in this case, <code>TagsHierarchy</code>) will be added automatically, so you don't need to create it.

      class CreateTagHierarchy < ActiveRecord::Migration
        def change
          create_table :tags_hierarchy do |t|
            t.integer  :ancestor_id, :null => false   # ID of the parent/grandparent/great-grandparent/... tag
            t.integer  :descendant_id, :null => false # ID of the target tag
            t.integer  :generations, :null => false   # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
          end

          # For "all progeny of..." selects:
          add_index :tags_hierarchy, [:ancestor_id, :descendant_id], :unique => true

          # For "all ancestors of..." selects
          add_index :tags_hierarchy, [:descendant_id]
        end
      end

6.  Run <code>rake db:migrate</code>

7.  If you're migrating away from another system where your model already has a
    <code>parent_id</code> column, run <code>Tag.rebuild!</code> and the
    ..._hierarchy table will be truncated and rebuilt.

    If you're starting from scratch you don't need to call <code>rebuild!</code>.

== Usage

=== Creation

Create a root node:

  grandparent = Tag.create!(:name => 'Grandparent')

There are two equivalent ways to add children. Either use the <code>add_child</code> method:

  parent = Tag.create!(:name => 'Parent')
  grandparent.add_child parent

Or append to the <code>children</code> collection:

  child = Tag.create!(:name => 'Child')
  parent.children << child

You should have something that resembles this:

  grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")

* Grandparent
  * Parent
    * Child

== Accessing Data

=== Class methods

[Tag.root] returns an arbitrary root node
[Tag.roots] returns all root nodes
[Tag.leaves] returns all leaf nodes

=== Instance methods

[tag.root] returns the root for this node
[tag.root?] returns true if this is a root node
[tag.child?] returns true if this is a child node. It has a parent.
[tag.leaf?] returns true if this is a leaf node. It has no children.
[tag.level] returns the level, or "generation", for this node in the tree. A root node = 0
[tag.parent] returns the node's immediate parent
[tag.children] returns an array of immediate children (just those in the next level).
[tag.ancestors] returns an array of all parents, parents' parents, etc, excluding self.
[tag.self_and_ancestors] returns an array of all parents, parents' parents, etc, including self.
[tag.siblings] returns an array of brothers and sisters (all at that level), excluding self.
[tag.self_and_siblings] returns an array of brothers and sisters (all at that level), including self.
[tag.descendants] returns an array of all children, childrens' children, etc., excluding self.
[tag.self_and_descendants] returns an array of all children, childrens' children, etc., including self.

== Thanks to

* https://github.com/collectiveidea/awesome_nested_set/
* https://github.com/patshaughnessy/class_factory/<commit_msg>doc tweaks<commit_after>= Closure Tree

Closure Tree is a mostly-API-compatible replacement for the
acts_as_tree and awesome_nested_set gems, but with much better
mutation performance thanks to the Closure Tree storage algorithm.

See {<NAME>}[http://karwin.blogspot.com/]'s excellent
{Models for hierarchical data presentation}[http://www.slideshare.net/billkarwin/models-for-hierarchical-data]
for a description of different tree storage algorithms.

== Setup

Note that closure_tree is being developed for Rails 3.1.0.rc1

1.  Add this to your Gemfile: <code>gem 'closure_tree'</code>

2.  Run <code>bundle install</code>

3.  Add <code>acts_as_tree</code> to your hierarchical model(s).

4.  Add a migration to add a <code>parent_id</code> column to the model you want to act_as_tree.

    Note that if the column is null, the tag will be considered a root node.

      class AddParentIdToTag < ActiveRecord::Migration
        def change
          add_column :tag, :parent_id, :integer
        end
      end

5.  Add a database migration to store the hierarchy for your model. By
    convention the table name will be the model's table name, followed by
    "_hierarchy". Note that by calling <code>acts_as_tree</code>, a "virtual model" (in this case, <code>TagsHierarchy</code>) will be added automatically, so you don't need to create it.

      class CreateTagHierarchy < ActiveRecord::Migration
        def change
          create_table :tags_hierarchy do |t|
            t.integer  :ancestor_id, :null => false   # ID of the parent/grandparent/great-grandparent/... tag
            t.integer  :descendant_id, :null => false # ID of the target tag
            t.integer  :generations, :null => false   # Number of generations between the ancestor and the descendant. Parent/child = 1, for example.
          end

          # For "all progeny of..." selects:
          add_index :tags_hierarchy, [:ancestor_id, :descendant_id], :unique => true

          # For "all ancestors of..." selects
          add_index :tags_hierarchy, [:descendant_id]
        end
      end

6.  Run <code>rake db:migrate</code>

7.  If you're migrating away from another system where your model already has a
    <code>parent_id</code> column, run <code>Tag.rebuild!</code> and the
    ..._hierarchy table will be truncated and rebuilt.

    If you're starting from scratch you don't need to call <code>rebuild!</code>.

== Usage

=== Creation

Create a root node:

  grandparent = Tag.create!(:name => 'Grandparent')

There are two equivalent ways to add children. Either use the <code>add_child</code> method:

  parent = Tag.create!(:name => 'Parent')
  grandparent.add_child parent

Or append to the <code>children</code> collection:

  child = Tag.create!(:name => 'Child')
  parent.children << child

Then:

  puts grandparent.self_and_descendants.collect{ |t| t.name }.join(" > ")
  "grandparent > parent > child"

== Accessing Data

=== Class methods

[Tag.root] returns an arbitrary root node
[Tag.roots] returns all root nodes
[Tag.leaves] returns all leaf nodes

=== Instance methods

[tag.root] returns the root for this node
[tag.root?] returns true if this is a root node
[tag.child?] returns true if this is a child node. It has a parent.
[tag.leaf?] returns true if this is a leaf node. It has no children.
[tag.level] returns the level, or "generation", for this node in the tree. A root node = 0
[tag.parent] returns the node's immediate parent
[tag.children] returns an array of immediate children (just those in the next level).
[tag.ancestors] returns an array of all parents, parents' parents, etc, excluding self.
[tag.self_and_ancestors] returns an array of all parents, parents' parents, etc, including self.
[tag.siblings] returns an array of brothers and sisters (all at that level), excluding self.
[tag.self_and_siblings] returns an array of brothers and sisters (all at that level), including self.
[tag.descendants] returns an array of all children, childrens' children, etc., excluding self.
[tag.self_and_descendants] returns an array of all children, childrens' children, etc., including self.

== Thanks to

* https://github.com/collectiveidea/awesome_nested_set
* https://github.com/patshaughnessy/class_factory
{'fraction_non_alphanumeric': 0.09435957696827262, 'fraction_numerical': 0.003055229142185664, 'mean_word_length': 3.6944291230005515, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 71, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5745399', 'n_tokens_mistral': 2557, 'n_tokens_neox': 2463, 'n_words': 1001}