1 # vim: ts=8:sw=4:sts=4:et
2 package DBIx::Class::Tree::AdjacencyList;
5 use base qw( DBIx::Class );
10 DBIx::Class::Tree::AdjacencyList - Manage a tree of data using the common adjacency list model. (EXPERIMENTAL)
14 Create a table for your tree data.
16 CREATE TABLE employees (
17 employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
18 parent_id INTEGER NOT NULL DEFAULT 0,
22 In your Schema or DB class add Tree::AdjacencyList to the top
23 of the component list.
25 __PACKAGE__->load_components(qw( Tree::AdjacencyList ... ));
27 Specify the column that contains the parent ID of each row.
30 __PACKAGE__->parent_column('parent_id');
32 Thats it, now you can modify and analyze the tree.
37 my $employee = My::Employee->create({ name=>'Matt S. Trout' });
39 my $rs = $employee->children();
40 my @siblings = $employee->children();
42 my $parent = $employee->parent();
43 $employee->parent( 7 );
47 This module provides methods for working with adjacency lists. The
48 adjacency list model is a very common way of representing a tree structure.
49 In this model each row in a table has a prent ID column that references the
50 primary key of another row in the same table. Because of this the primary
51 key must only be one column and is usually some sort of integer. The row
52 with a parent ID of 0 is the root node and is usually the parent of all
53 other rows. Although, there is no limitation in this module that would
54 stop you from having multiple root nodes.
60 __PACKAGE__->parent_column('parent_id');
62 Declares the name of the column that contains the self-referential
63 ID which defines the parent row. Defaults to "parent_id". This
64 will create a has_many (children) and belongs_to (parent)
69 __PACKAGE__->mk_classdata( '_parent_column' => 'parent_id' );
74 my $parent_col = shift;
75 my $primary_col = ($class->primary_columns())[0];
76 $class->belongs_to( '_parent' => $class => { "foreign.$primary_col" => "self.$parent_col" } );
77 $class->has_many( 'children' => $class => { "foreign.$parent_col" => "self.$primary_col" } );
78 $class->_parent_column( $parent_col );
81 return $class->_parent_column();
86 my $parent = $employee->parent();
87 $employee->parent( $parent_obj );
88 $employee->parent( $parent_id );
90 Retrieves the object's parent object, or changes the object's
91 parent to the specified parent or parent ID. If you would like
92 to make the object the root node, just set the parent to 0.
94 If you are setting the parent then 0 will be returned if the
95 specified parent is already the object's parent and 1 on
103 my $new_parent = shift;
104 my $parent_col = $self->_parent_column();
105 if (ref($new_parent)) {
106 $new_parent = $new_parent->id() || croak('Parent object does not have an ID');;
108 return 0 if ($new_parent == ($self->get_column($parent_col)||0));
109 $self->set_column( $parent_col => $new_parent );
113 return $self->_parent();
118 my $children_rs = $employee->children();
119 my @children = $employee->children();
121 Returns a list or record set, depending on context, of all
122 the objects one level below the current one. This method
123 is created when parent_column() is called, which sets up a
124 has_many relationship called children.
128 $parent->attach_child( $child );
129 $parent->attach_child( $child, $child, ... );
131 Sets the child, or children, to the new parent. Returns 1
132 on success and returns 0 if the parent object already has
140 foreach my $child (@_) {
141 $child->parent( $self );
148 my $rs = $node->siblings();
149 my @siblings = $node->siblings();
151 Returns either a result set or an array of all other objects
152 with the same parent as the calling object.
158 my $parent_col = $self->_parent_column;
159 my $primary_col = ($self->primary_columns())[0];
160 my $rs = $self->result_source->resultset->search(
162 $parent_col => $self->get_column($parent_col),
163 $primary_col => { '!=' => $self->get_column($primary_col) },
166 return $rs->all() if (wantarray());
172 =head2 attach_sibling
174 $obj->attach_sibling( $sibling );
175 $obj->attach_sibling( $sibling, $sibling, ... );
177 Sets the passed in object(s) to have the same parent
178 as the calling object. Returns 1 on success and
179 0 if the sibling already has the same parent.
186 foreach my $node (@_) {
187 $return = 0 if (!$node->parent( $self->parent() ));
197 Aran Clary Deltac <bluefeet@cpan.org>
201 You may distribute this code under the same terms as Perl itself.