Added INHERITED METHODS sections
[dbsrgits/DBIx-Class-Tree.git] / lib / DBIx / Class / Tree / AdjacencyList.pm
CommitLineData
87427fdb 1# vim: ts=8:sw=4:sts=4:et
2package DBIx::Class::Tree::AdjacencyList;
3use strict;
4use warnings;
5use base qw( DBIx::Class );
6use Carp qw( croak );
7
8=head1 NAME
9
10DBIx::Class::Tree::AdjacencyList - Manage a tree of data using the common adjacency list model. (EXPERIMENTAL)
11
12=head1 SYNOPSIS
13
14Create a table for your tree data.
15
16 CREATE TABLE employees (
17 employee_id INTEGER PRIMARY KEY AUTOINCREMENT,
82958127 18 parent_id INTEGER NOT NULL DEFAULT 0,
87427fdb 19 name TEXT NOT NULL
20 );
21
22In your Schema or DB class add Tree::AdjacencyList to the top
23of the component list.
24
25 __PACKAGE__->load_components(qw( Tree::AdjacencyList ... ));
87427fdb 26
57f04bd5 27Specify the column that contains the parent ID of each row.
87427fdb 28
29 package My::Employee;
30 __PACKAGE__->parent_column('parent_id');
31
32Thats it, now you can modify and analyze the tree.
33
82958127 34 #!/usr/bin/perl
87427fdb 35 use My::Employee;
36
37 my $employee = My::Employee->create({ name=>'Matt S. Trout' });
38
39 my $rs = $employee->children();
40 my @siblings = $employee->children();
41
42 my $parent = $employee->parent();
43 $employee->parent( 7 );
44
45=head1 DESCRIPTION
46
47This module provides methods for working with adjacency lists. The
48adjacency list model is a very common way of representing a tree structure.
49In this model each row in a table has a prent ID column that references the
50primary key of another row in the same table. Because of this the primary
51key must only be one column and is usually some sort of integer. The row
9717d3ca 52with a parent ID of 0 is the root node and is usually the parent of all
53other rows. Although, there is no limitation in this module that would
54stop you from having multiple root nodes.
87427fdb 55
56=head1 METHODS
57
58=head2 parent_column
59
60 __PACKAGE__->parent_column('parent_id');
61
62Declares the name of the column that contains the self-referential
82958127 63ID which defines the parent row. Defaults to "parent_id". This
64will create a has_many (children) and belongs_to (parent)
65relationship.
87427fdb 66
87427fdb 67=cut
68
82958127 69__PACKAGE__->mk_classdata( '_parent_column' => 'parent_id' );
70
71sub parent_column {
72 my $class = shift;
73 if (@_) {
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 );
79 return 1;
80 }
81 return $class->_parent_column();
82}
87427fdb 83
84=head2 parent
85
86 my $parent = $employee->parent();
87 $employee->parent( $parent_obj );
88 $employee->parent( $parent_id );
89
82958127 90Retrieves the object's parent object, or changes the object's
9717d3ca 91parent to the specified parent or parent ID. If you would like
92to make the object the root node, just set the parent to 0.
93
94If you are setting the parent then 0 will be returned if the
95specified parent is already the object's parent and 1 on
96success.
87427fdb 97
87427fdb 98=cut
99
100sub parent {
82958127 101 my $self = shift;
102 if (@_) {
103 my $new_parent = shift;
104 my $parent_col = $self->_parent_column();
87427fdb 105 if (ref($new_parent)) {
82958127 106 $new_parent = $new_parent->id() || croak('Parent object does not have an ID');;
87427fdb 107 }
82958127 108 return 0 if ($new_parent == ($self->get_column($parent_col)||0));
109 $self->set_column( $parent_col => $new_parent );
87427fdb 110 $self->update();
111 return 1;
112 }
82958127 113 return $self->_parent();
87427fdb 114}
115
116=head2 children
117
118 my $children_rs = $employee->children();
119 my @children = $employee->children();
120
121Returns a list or record set, depending on context, of all
82958127 122the objects one level below the current one. This method
123is created when parent_column() is called, which sets up a
124has_many relationship called children.
87427fdb 125
126=head2 attach_child
127
128 $parent->attach_child( $child );
9717d3ca 129 $parent->attach_child( $child, $child, ... );
87427fdb 130
9717d3ca 131Sets the child, or children, to the new parent. Returns 1
132on success and returns 0 if the parent object already has
133the child.
87427fdb 134
135=cut
136
137sub attach_child {
9717d3ca 138 my $self = shift;
139 my $return = 1;
140 foreach my $child (@_) {
141 $child->parent( $self );
142 }
143 return $return;
87427fdb 144}
145
82958127 146=head2 siblings
147
148 my $rs = $node->siblings();
149 my @siblings = $node->siblings();
150
151Returns either a result set or an array of all other objects
152with the same parent as the calling object.
153
154=cut
155
156sub siblings {
157 my( $self ) = @_;
158 my $parent_col = $self->_parent_column;
159 my $primary_col = ($self->primary_columns())[0];
160 my $rs = $self->result_source->resultset->search(
161 {
162 $parent_col => $self->get_column($parent_col),
163 $primary_col => { '!=' => $self->get_column($primary_col) },
164 },
165 );
166 return $rs->all() if (wantarray());
167 return $rs;
168}
169
170=cut
171
87427fdb 172=head2 attach_sibling
173
9717d3ca 174 $obj->attach_sibling( $sibling );
175 $obj->attach_sibling( $sibling, $sibling, ... );
87427fdb 176
9717d3ca 177Sets the passed in object(s) to have the same parent
178as the calling object. Returns 1 on success and
1790 if the sibling already has the same parent.
87427fdb 180
181=cut
182
183sub attach_sibling {
9717d3ca 184 my $self = shift;
185 my $return = 1;
186 foreach my $node (@_) {
187 $return = 0 if (!$node->parent( $self->parent() ));
188 }
189 return $return;
87427fdb 190}
191
87427fdb 1921;
193__END__
194
4b44af23 195=head1 INHERITED METHODS
196
197=head2 DBIx::Class
198
199=over 4
200
201=item *
202
203L<mk_classdata|DBIx::Class/mk_classdata>
204
205=item *
206
207L<component_base_class|DBIx::Class/component_base_class>
208
209=back
210
211=head2 DBIx::Class::Componentised
212
213=over 4
214
215=item *
216
217L<inject_base|DBIx::Class::Componentised/inject_base>
218
219=item *
220
221L<load_components|DBIx::Class::Componentised/load_components>
222
223=item *
224
225L<load_own_components|DBIx::Class::Componentised/load_own_components>
226
227=back
228
229=head2 Class::Data::Accessor
230
231=over 4
232
233=item *
234
235L<mk_classaccessor|Class::Data::Accessor/mk_classaccessor>
236
237=back
238
87427fdb 239=head1 AUTHOR
240
241Aran Clary Deltac <bluefeet@cpan.org>
242
243=head1 LICENSE
244
245You may distribute this code under the same terms as Perl itself.
246