From: Arthur Axel "fREW" Schmidt Date: Fri, 20 Aug 2010 20:35:00 +0000 (+0000) Subject: Add patch for nebulous X-Git-Tag: 0.03002~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3c94ae56c4e2a8553d44944a111f479b0a87ff7d;p=dbsrgits%2FDBIx-Class-Tree.git Add patch for nebulous --- diff --git a/Changes b/Changes index cf049ba..441e145 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for DBIx::Class::Tree + - Added ordered ancesors (nebulous) + 0.03001 2010-04-25 - Fixed the parents (note the plural) relationship to not have cascade_copy set by default diff --git a/lib/DBIx/Class/Tree/AdjacencyList.pm b/lib/DBIx/Class/Tree/AdjacencyList.pm index 285d5de..d913113 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,13 @@ 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) +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. -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 setups an additional has_many relationship called +parents which is useful when you want to treat an adjacency list as a DAG. =cut @@ -134,12 +134,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 +171,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 +219,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 +230,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 +240,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 +260,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 +284,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 @@ -316,7 +335,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 +347,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 diff --git a/t/lib/TreeTest.pm b/t/lib/TreeTest.pm index 0e66aa6..7af89b3 100644 --- a/t/lib/TreeTest.pm +++ b/t/lib/TreeTest.pm @@ -9,7 +9,7 @@ use TreeTest::Schema; our $NODE_COUNT = 80; sub count_tests { - my $count = 14; + my $count = 17; if( TreeTest::Schema::Node->can('position_column') ){ $count ++; } @@ -51,6 +51,11 @@ sub run_tests { ok( ($nodes->find(22)->parents->count()==1), 'node 22 has correct number of parents' ); ok( (($nodes->find(22)->parents->all())[0]->id()==$nodes->find(22)->parent->id()), 'node 22 parent matches parents' ); + my @ancestors = $nodes->find(44)->ancestors(); + ok( scalar(@ancestors)==8, 'node 44 has correct number of ancestors' ); + ok( $ancestors[0]->id == $nodes->find(44)->parent_id, 'node 44\'s first ancestor is its parent' ); + ok( $ancestors[-1]->name eq 'root', 'node 44\'s last ancestor is root' ); + if( TreeTest::Schema::Node->can('position_column') ){ ok( check_positions(scalar $root->children()), 'positions are correct' ); }