Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
DBIx::Class::Tree::NesUsereContributed Perl DocDBIx::Class::Tree::NestedSet(3)

NAME
       DBIx::Class::Tree::NestedSet - Manage trees of data using the nested
       set model

SYNOPSIS
       Create a	table for your tree data.

	   CREATE TABLE	Department (
	     id	      INTEGER PRIMARY KEY AUTOINCREMENT,
	     root_id  integer,
	     lft      integer NOT NULL,
	     rgt      integer NOT NULL,
	     level    integer NOT NULL,
	     name     text NOT NULL,
	   );

       In your Schema or DB class add Tree::NestedSet to the top of the
       component list.

	 __PACKAGE__->load_components(qw( Tree::NestedSet ... ));

       Specify the columns required by the module.

	 package My::Department;
	 __PACKAGE__->tree_columns({
	     root_column     =>	'root_id',
	     left_column     =>	'lft',
	     right_column    =>	'rgt',
	     level_column    =>	'level',
	 });

       Using it:

	 my $root	 = My::Department->create({ ...	});
	 my $child	 = $root->add_to_children({ ...	});

	 my $rs		 = $root->children;
	 my @descendants = $root->children;

	 my $parent	 = $child->parent;
	 my $rs		 = $child->ancestors;
	 my @ancestors	 = $child->ancestors;

DESCRIPTION
       This module provides methods for	working	with nested set	trees. The
       nested tree model is a way of representing hierarchical information in
       a database. This	takes a	different approach to the Adjacency List
       implementation. (see DBIx::Class::Tree::AdjacencyList which uses
       "parent"	relationships in a recursive manner.

       The NestedSet implementation can	be more	efficient for most searches
       than the	Adjacency List Implementation, for example, to obtain all
       descendants requires recursive queries in the Adjacency List
       implementation but is a single query in the NestedSet implementation.

       The trade-off is	that NestedSet inserts are more	expensive so it	is
       most useful if you have an application that does	many reads but few
       inserts.

       More about NestedSets can be found at
       <http://en.wikipedia.org/wiki/Nested_set_model>

       Oh, and although	I give some code examples of familial relationships
       (where there are	usually	two parents), both Adjacency List and
       NestedSet implementations can only have one parent.

RELATIONS
       This module automatically creates several relationships.

   root
	 $root_node = $node->root;

       A belongs_to relation to	the root of $nodes tree.

   nodes
	 $all_nodes = $node->nodes;
	 $new_node  = $node->add_to_nodes({name	=> 'Mens Wear'});

       A has_many relationship to all the nodes	of $nodes tree.

       Adding to this relationship creates a rightmost child to	$node.

   parent
	 $parent = $node->parent;

       A belongs_to relationship to the	parent node of $nodes tree.

       Note that only the root node does not have a parent.

   children
	 $rs	      =	$node->children;
	 @children    =	$node->children;
	 $child	      =	$node->add_to_children({name =>	'Toys'});

       A has_many relation to the children of $node.

       Adding to this relationship creates a rightmost child to	$node.

   descendants
	 $rs	      =	$node->descendants;
	 @descendants =	$node->descendants;
	 $child	      =	$node->add_to_descendants({name	=> 'Mens Wear'});

       A has_many relation to the descendants of $node.

       Adding to this relationship creates a rightmost child to	$node.

   ancestors
	 $rs	      =	$node->ancestors;
	 @ancestors   =	$node->ancestors;
	 $parent      =	$node->add_to_ancestors({name => 'Head office'});

       A has_many relation to the ancestors of $node.

       Adding to this relationship creates a new node in place of $node	and
       makes it	the parent of $node. All descendants of	$node will likewise be
       pushed town the hierarchy.

METHODS
       Many methods have alternative names, e.g. "left_siblings" and
       "previous_siblings"

       This is in deference to the DBIx::Class::Ordered	module which uses
       terms "previous"	"next" "first" and "last".

       Similarly DBIx::Class::Tree::AdjacencyList::Ordered uses	terms
       "append", "prepend", "before" and "after"

       However,	my preference to use terms "left" and "right" consistently
       when using this module. However,	the other names	are available if you
       are more	familiar with those modules.

   tree_columns
	 __PACKAGE__->tree_columns({
	     left_column   => 'lft',
	     right_column  => 'rgt',
	     root_column   => 'root_id',
	     level_column  => 'level',
	 });

       Declare the name	of the columns defined in the database schema.

       None of these columns should be modified	outside	if this	module.
       left_column and right_column are	unlikely to be of any use to your
       application. They should	be integer fields.

       Multiple	trees are allowed in the same table, each tree will have a
       unique value in the root_column.	In the current implementation this
       should be an integer field

       The level_column	may be of use in your application, it defines the
       depth of	each node in the tree (with the	root at	level zero).

   create
	 my $tree    = $schema->resultset('My::Department')->create({
	     name    = 'Head Office',
	 });

	 my $tree    = $schema->resultset('My::Department')->create({
	     name    = 'UK Office',
	     root_id = $uk_office_ident,
	 });

       Creates a new root node.

       If the root_column (root_id) is not provided then it defaults to
       producing a node	where the root_column has the same value as the
       primary key. This will croak if the table is defined with multiple key
       primary index.

       Note that no checks (yet) are made to stop you creating another key
       with the	same root_id as	an existing tree. If you do so you will	get
       into a terrible mess!

   delete
	 $department->delete;

       This will delete	the node and all descendants. Cascade Delete is	turned
       off in the has_many relationships "nodes" "children" "descendants" so
       that delete DTRT.

   is_root
	 if ($node->is_root) {
	     print "Node is a root\n";
	 }

       Returns true if the $node is a root node

   is_branch
	 $has_children = $node->is_branch;

       Returns true if the node	is a branche (i.e. has children)

   is_leaf
	 $is_terminal_node = $node->is_leaf;

       Returns true if the node	is a leaf (i.e.	it has no children)

   siblings
	 @siblings    =	$node->siblings;
	 $siblings_rs =	$node->siblings;

       Returns all siblings of this $node excluding $node itself.

       Since a root node has no	siblings it returns undef.

   left_siblings (or previous_siblings)
	 @younger_siblings    =	$node->left_siblings;
	 $younger_siblings_rs =	$node->left_siblings;

       Returns all siblings of this $node to the left this $node.

       Since a root node has no	siblings it returns undef.

   right_siblings (or next_siblings)
	 @older_siblings      =	$node->right_siblings;
	 $older_siblings_rs   =	$node->right_siblings;

       Returns all siblings of this $node to the right of this $node.

       Since a root node has no	siblings it returns undef.

   left_sibling	(or previous_sibling)
	 $younger_sibling = $node->left_sibling;

       Returns the sibling immediately to the left of this $node (if any).

   right_sibling (or next_sibling)
	 $older_sibling	= $node->right_sibling;

       Returns the sibling immediately to the right of this $node (if any).

   leftmost_sibling (or	first_sibling)
	 $youngest_sibling = $node->leftmost_sibling;

       Returns the left	most sibling relative to this $node (if	any).

       Does not	return this $node if this node is the leftmost sibling.

   rightmost_sibling (or last_sibling)
	 $oldest_sibling = $node->rightmost_sibling;

       Returns the right most sibling relative to this $node (if any).

       Does not	return this $node if this node is the rightmost	sibling.

   CREATE METHODS
       The following create methods create a new node in relation to an
       existing	node.

   create_right_sibling
	 $bart->create_right_sibling({ name => 'Lisa' });

       Create a	new node as a right sibling to $bart.

   create_left_sibling
	 $bart->create_left_sibling({ name => 'Maggie' });

       Create a	new node as a left sibling to $bart.

   create_rightmost_child
	 $homer->create_rightmost_child({ name => 'Lisa' });

       Create a	new node as a rightmost	child to $homer

   create_leftmost_child
	 $homer->create_leftmost_child({ name => 'Maggie' });

       Create a	new node as a leftmost child to	$homer

   ATTACH METHODS
       The following attach methods take an existing node (and all of it's
       descendants) and	attaches them to the tree in relation to an existing
       node.

       The node	being inserted can either be from the same tree	(as identified
       by the root_column) or from another tree. If the	root of	another	tree
       is attached then	the whole of that tree becomes a sub-tree of this
       node's tree.

       The only	restriction is that the	node being attached cannot be an
       ancestor	of this	node.

       When attaching multiple nodes we	try to DWIM so that the	order they are
       specified in the	call represents	the order they appear in the siblings
       list.

       e.g. if we had a	parent with children A,B,C,D,E

       and we attached nodes 1,2,3 in the following calls, we expect the
       following results.

	 $parent->attach_rightmost_child    1,2,3 gives	us children A,B,C,D,E,1,2,3

	 $parent->attach_leftmost_child	    1,2,3 gives	us children 1,2,3,A,B,C,D,E

	 $child_C->attach_right_sibling	    1,2,3 gives	us children A,B,C,1,2,3,D,E

	 $child_C->attach_left_sibling	    1,2,3 gives	us children A,B,1,2,3,C,D,E

	 $child_C->attach_rightmost_sibling 1,2,3 gives	us children A,B,C,D,E,1,2,3

	 $child_C->attach_leftmost_sibling  1,2,3 gives	us children 1,2,3,A,B,C,D,E

   attach_rightmost_child (or append_child)
	 $parent->attach_rightmost_child($other_node);
	 $parent->attach_rightmost_child($other_node_1,	$other_node_2, ...);

       Attaches	the other_nodes	to $parent as the rightmost children.

   attach_leftmost_child
	 $parent->attach_leftmost_child($other_node);
	 $parent->attach_leftmost_child($other_node_1, $other_node_2, ...);

       Attaches	the other_nodes	to $parent as the leftmost children.

   attach_right_sibling	(or attach_after)
	 $node->attach_right_sibling($other_node);
	 $node->attach_right_sibling($other_node_1, $other_node_2, ...);

       Attaches	the other_nodes	to $node as it's siblings.

   attach_left_sibling
	 $node->attach_left_sibling($other_node);
	 $node->attach_left_sibling($other_node_1, $other_node_2, ...);

       Attaches	the other_nodes	to $node as it's left siblings.

   attach_rightmost_sibling
	 $node->attach_rightmost_sibling($other_node);
	 $node->attach_rightmost_sibling($other_node_1,	$other_node_2, ...);

       Attaches	the other_nodes	to $node as it's rightmost siblings.

   attach_leftmost_sibling
	 $node->attach_leftmost_sibling($other_node);
	 $node->attach_leftmost_sibling($other_node_1, $other_node_2, ...);

       Attaches	the other_nodes	to $node as it's leftmost siblings.

   move_left (or move_previous)
	 $node->move_left;

       Exchange	the $node with the sibling immediately to the left and return
       the node	it exchanged with.

       If the $node is already the leftmost node then no exchange takes	place
       and the method returns undef.

   move_right (or move_next)
	 $node->move_right;

       Exchange	the $node with the sibling immediately to the right and	return
       the node	it exchanged with.

       If the $node is already the rightmost node then no exchange takes place
       and the method returns undef.

   move_leftmost (or move_first)
	 $node->move_leftmost;

       Exchange	the $node with the leftmost sibling and	return the node	it
       exchanged with.

       If the $node is already the leftmost node then no exchange takes	place
       and the method returns undef.

   move_rightmost (or move_last)
	 $node->move_rightmost;

       Exchange	the $node with the rightmost sibling and return	the node it
       exchanged with.

       If the $node is already the rightmost node then no exchange takes place
       and the method returns undef.

   CUTTING METHODS
   take_cutting
       Cuts the	invocant and its descendants out of the	tree they are in,
       making the invocant the root of a new tree. Returns the modified
       invocant.

   dissolve
       Dissolves the entire thread, that is turn each node of the thread into
       a single-item tree of its own.

CAVEATS
   Multiple Column Primary Keys
       Support for Multiple Column Primary Keys	is limited (mainly because I
       rarely use them)	but I have tried to make it possible to	use them.
       Please let me know if this does not work	as well	as you expect.

   discard_changes
       By the nature of	Nested Set implementations, moving, inserting or
       deleting	nodes in the tree will potentially update many (sometimes
       most) other nodes.

       Even if you have	preloaded some of the objects, if you make a change to
       one object the other objects will not reflect their new value until you
       have reloaded them from the database.  (see "discard_changes" in
       DBIx::Class::Row)

       A simple	demonstration of this

	 $grampa   = $schema->schema->resultset('Simpsons')->create({ name => 'Abraham'	});
	 $homer	   = $grampa->add_children({name => 'Homer'});
	 $bart	   = $homer->add_children({name	=> 'Bart'});

       The methods in this module will do their	best to	keep instances that
       they know about updated.	For example the	first call to "add_children"
       in the above example will update	$grampa	and $homer with	the latest
       changes to the database.

       However,	the second call	to "add_children" only knows about $homer and
       $bart and in adding a new node to the tree it will update the $grampa
       node in the database. To	ensure you have	the latest changes do the
       following.

	 $grampa->discard_changes.

       Not doing so will have unpredictable results.

AUTHORS
       Code by Ian Docherty <pause@iandocherty.com>

       Based on	original code by Florian Ragwitz <rafl@debian.org>

       Incorporating ideas and code from Pedro Melo <melo@simplicidade.org>

       Special thanks to Moritz	Lenz who sent in lots of patches and changes
       for version 0.08

COPYRIGHT AND LICENSE
       Copyright (c) 2009-2011 The above authors

       This is free software; you can redistribute it and/or modify it under
       the same	terms as Perl itself, either Perl version 5.10.0 or, at	your
       option, any later version of Perl 5 you may have	available.

perl v5.32.0			  2011-09-22   DBIx::Class::Tree::NestedSet(3)

NAME | SYNOPSIS | DESCRIPTION | RELATIONS | METHODS | CAVEATS | AUTHORS | COPYRIGHT AND LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=DBIx::Class::Tree::NestedSet&sektion=3&manpath=FreeBSD+12.2-RELEASE+and+Ports>

home | help