X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FTree%2FAdjacencyList.pm;h=a77eeda0f36f9c0a869bfe02fc9d7ca8cb0c0323;hb=refs%2Fheads%2Fmaster;hp=285d5de9c87669f1653e8a89d2df170529b96f0f;hpb=1dfd20a478d120b18700428d45f03e19b445bee4;p=dbsrgits%2FDBIx-Class-Tree.git diff --git a/lib/DBIx/Class/Tree/AdjacencyList.pm b/lib/DBIx/Class/Tree/AdjacencyList.pm index 285d5de..a77eeda 100644 --- a/lib/DBIx/Class/Tree/AdjacencyList.pm +++ b/lib/DBIx/Class/Tree/AdjacencyList.pm @@ -21,7 +21,7 @@ Create a table for your tree data. name TEXT NOT NULL ); -In your Schema or DB class add Tree::AdjacencyList to the top +In your Schema or DB class add Tree::AdjacencyList to the top of the component list. __PACKAGE__->load_components(qw( Tree::AdjacencyList ... )); @@ -39,24 +39,24 @@ Thats it, now you can modify and analyze the tree. #!/usr/bin/perl use My::Employee; - + my $employee = My::Employee->create({ name=>'Matt S. Trout' }); - + my $rs = $employee->children(); my @siblings = $employee->children(); - + my $parent = $employee->parent(); $employee->parent( 7 ); =head1 DESCRIPTION -This module provides methods for working with adjacency lists. The -adjacency list model is a very common way of representing a tree structure. -In this model each row in a table has a prent ID column that references the -primary key of another row in the same table. Because of this the primary -key must only be one column and is usually some sort of integer. The row -with a parent ID of 0 is the root node and is usually the parent of all -other rows. Although, there is no limitation in this module that would +This module provides methods for working with adjacency lists. The +adjacency list model is a very common way of representing a tree structure. +In this model each row in a table has a prent ID column that references the +primary key of another row in the same table. Because of this the primary +key must only be one column and is usually some sort of integer. The row +with a parent ID of 0 is the root node and is usually the parent of all +other rows. Although, there is no limitation in this module that would stop you from having multiple root nodes. =head1 METHODS @@ -65,13 +65,12 @@ stop you from having multiple root nodes. __PACKAGE__->parent_column('parent_id'); -Declares the name of the column that contains the self-referential -ID which defines the parent row. Defaults to "parent_id". This -will create a has_many (children) and belongs_to (parent) -relationship. +Declares the name of the column that contains the self-referential +ID which defines the parent row. This will create a has_many (children) +and belongs_to (parent) relationship. -This method also setups an additional has_many relationship called -parents which is useful when you want to treat an adjacency list +This method also sets up an additional has_many relationship called +parents which is useful when you want to treat an adjacency list as a DAG. =cut @@ -114,7 +113,7 @@ And you execute: $b->parent( $d ); -Since D is a descendant of B then all of B's siblings get their parent +Since D is a descendant of B then all of D's siblings get their parent changed to A. Then B's parent is set to D. A @@ -134,12 +133,12 @@ __PACKAGE__->mk_classdata( 'repair_tree' => 0 ); $employee->parent( $parent_obj ); $employee->parent( $parent_id ); -Retrieves the object's parent object, or changes the object's -parent to the specified parent or parent ID. If you would like +Retrieves the object's parent object, or changes the object's +parent to the specified parent or parent ID. If you would like to make the object the root node, just set the parent to 0. -If you are setting the parent then 0 will be returned if the -specified parent is already the object's parent and 1 on +If you are setting the parent then 0 will be returned if the +specified parent is already the object's parent and 1 on success. =cut @@ -171,6 +170,25 @@ sub parent { } return $self->_parent(); } +=head2 ancestors + + @list = $employee->ancestors(); + +Returns a list of ancestors starting with a record's +parent and moving toward the tree root. + +=cut + +sub ancestors { + my $self = shift; + my @ancestors = (); + my $rec = $self; + while ($rec = $rec->parent) { + push(@ancestors, $rec); + } + return @ancestors; +} + =head2 has_descendant @@ -200,10 +218,10 @@ sub has_descendant { my $parents = $node->parents(); my @parents = $node->parents(); -This has_many relationship is not that useful as it will -never return more than one parent due to the one-to-many -structure of adjacency lists. The reason this relationship -is defined is so that this tree type may be treated as if +This has_many relationship is not that useful as it will +never return more than one parent due to the one-to-many +structure of adjacency lists. The reason this relationship +is defined is so that this tree type may be treated as if it was a DAG. =head2 children @@ -211,9 +229,9 @@ it was a DAG. my $children_rs = $employee->children(); my @children = $employee->children(); -Returns a list or record set, depending on context, of all -the objects one level below the current one. This method -is created when parent_column() is called, which sets up a +Returns a list or record set, depending on context, of all +the objects one level below the current one. This method +is created when parent_column() is called, which sets up a has_many relationship called children. =head2 attach_child @@ -221,8 +239,8 @@ has_many relationship called children. $parent->attach_child( $child ); $parent->attach_child( $child, $child, ... ); -Sets the child, or children, to the new parent. Returns 1 -on success and returns 0 if the parent object already has +Sets the child, or children, to the new parent. Returns 1 +on success and returns 0 if the parent object already has the child. =cut @@ -241,7 +259,7 @@ sub attach_child { my $rs = $node->siblings(); my @siblings = $node->siblings(); -Returns either a result set or an array of all other objects +Returns either a result set or an array of all other objects with the same parent as the calling object. =cut @@ -265,8 +283,8 @@ sub siblings { $obj->attach_sibling( $sibling ); $obj->attach_sibling( $sibling, $sibling, ... ); -Sets the passed in object(s) to have the same parent -as the calling object. Returns 1 on success and +Sets the passed in object(s) to have the same parent +as the calling object. Returns 1 on success and 0 if the sibling already has the same parent. =cut @@ -291,10 +309,7 @@ Returns 1 if the object has no children, and 0 otherwise. sub is_leaf { my( $self ) = @_; - my $has_child = $self->result_source->resultset->search( - { $self->_parent_column => $self->id() }, - { limit => 1 } - )->count(); + my $has_child = $self->children_rs->count(); return $has_child ? 0 : 1; } @@ -316,7 +331,7 @@ sub is_root { if ($obj->is_branch()) { ... } -Returns 1 if the object has a parent and has children. +Returns 1 if the object has a parent and has children. Returns 0 otherwise. =cut @@ -328,10 +343,10 @@ sub is_branch { =head2 set_primary_key -This method is an override of DBIx::Class' method for setting the -class' primary key column(s). This method passes control right on -to the normal method after first validating that only one column is -being selected as a primary key. If more than one column is then +This method is an override of DBIx::Class' method for setting the +class' primary key column(s). This method passes control right on +to the normal method after first validating that only one column is +being selected as a primary key. If more than one column is then an error will be thrown. =cut @@ -347,6 +362,30 @@ sub set_primary_key { 1; __END__ +=head1 CAVEATS + +=head2 Generated schemas + +If you are using L methods either directly +or via L or L, you +will need the following L hook to remove the constraint +from C, otherwise you will not be able to user 0 (zero) as +a value. + + sub sqlt_deploy_hook { + my ($self, $sqlt_table) = @_; + + foreach my $constraint ($sqlt_table->get_constraints) { + if ($constraint->field_names->[0] eq $self->parent_column) { + $sqlt_table->drop_constraint($constraint->name); + last; + } + } + } + +ALso see L for other examples. + =head1 INHERITED METHODS =head2 DBIx::Class