From: Aran Deltac Date: Mon, 27 Mar 2006 21:12:07 +0000 (+0000) Subject: Moved Positional code to a separate module. X-Git-Tag: 0.03001~23 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=57f04bd5f86029d4cf03f42e31dd5a307619f04c;p=dbsrgits%2FDBIx-Class-Tree.git Moved Positional code to a separate module. --- diff --git a/Build.PL b/Build.PL index de8c300..27dabe7 100644 --- a/Build.PL +++ b/Build.PL @@ -6,7 +6,7 @@ my %arguments = ( license => 'perl', module_name => 'DBIx::Class::Tree', requires => { - 'DBIx::Class' => 0.07, + 'DBIx::Class' => 0.05, }, build_requires => { 'DBD::SQLite' => 1.11, diff --git a/Changes b/Changes index 8909281..100c94c 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,8 @@ Revision history for DBIx::Class::Tree 0.01000 + - Moved Positional functionality out of AdjacencyList + and in to AdjacencyList::Positional. - AdjacencyList module created. - First version. diff --git a/lib/DBIx/Class/Tree/AdjacencyList.pm b/lib/DBIx/Class/Tree/AdjacencyList.pm index 93ccb16..4ceada2 100644 --- a/lib/DBIx/Class/Tree/AdjacencyList.pm +++ b/lib/DBIx/Class/Tree/AdjacencyList.pm @@ -23,11 +23,8 @@ In your Schema or DB class add Tree::AdjacencyList to the top of the component list. __PACKAGE__->load_components(qw( Tree::AdjacencyList ... )); - # If you want positionable data make sure this - # module comes first, as in: - __PACKAGE__->load_components(qw( Tree::AdjacencyList Positional ... )); -Specify the column that contains the parent ID each row. +Specify the column that contains the parent ID of each row. package My::Employee; __PACKAGE__->parent_column('parent_id'); @@ -64,9 +61,6 @@ other rows. Declares the name of the column that contains the self-referential ID which defines the parent row. Defaults to "parent_id". -If you are useing the L component then this -parent_column will automatically be used as the collection_column. - =cut __PACKAGE__->mk_classdata( 'parent_column' => 'parent_id' ); @@ -82,12 +76,6 @@ parent ID. If setting the parent ID then 0 will be returned if the object already has the specified parent, and 1 on success. -If you are using the L component this -module will first move the object to the last position of -the list, change the parent ID, then move the object to the -last position of the new list. This ensures the intergrity -of the positions. - =cut sub parent { @@ -98,13 +86,7 @@ sub parent { $new_parent = $new_parent->id() || 0; } return 0 if ($new_parent == ($self->get_column($parent_column)||0)); - $self->move_last() if ($self->positional()); $self->set_column( $parent_column => $new_parent ); - if ($self->positional()) { - $self->set_column( - $self->position_column() => $self->search( {$self->_collection_clause()} )->count() + 1 - ); - } $self->update(); return 1; } @@ -121,16 +103,12 @@ sub parent { Returns a list or record set, depending on context, of all the objects one level below the current one. -If you are using the L component then this method -will return the children sorted by the position column. - =cut sub children { my( $self ) = @_; my $rs = $self->search( - { $self->parent_column()=>$self->id() }, - ( $self->isa('DBIx::Class::Position') ? {order_by=>$self->position_column()} : () ) + { $self->parent_column()=>$self->id() } ); return $rs->all() if (wantarray()); return $rs; @@ -163,112 +141,6 @@ sub attach_sibling { $child->parent( $self->parent() ); } -=head1 POSITIONAL METHODS - -If you are useing the L component -in conjunction with this module then you will also have -these methods available to you. - -=head2 append_child - - $parent->append_child( $child ); - -Sets the child to have the specified parent and moves the -child to the last position. - -=cut - -sub append_child { - my( $self, $child ) = @_; - croak('This method may only be used with the Positional component') if (!$self->positional()); - $child->parent( $self ); -} - -=head2 prepend_child - - $parent->prepend_child( $child ); - -Sets the child to have the specified parent and moves the -child to the first position. - -=cut - -sub prepend_child { - my( $self, $child ) = @_; - croak('This method may only be used with the Positional component') if (!$self->positional()); - $child->parent( $self ); - $child->move_first(); -} - -=head2 attach_before - - $this->attach_before( $that ); - -Attaches the object at the position just before the -calling object's position. - -=cut - -sub attach_before { - my( $self, $sibling ) = @_; - croak('This method may only be used with the Positional component') if (!$self->positional()); - $sibling->parent( $self->parent() ); - $sibling->move_to( $self->get_column($self->position_column()) ); -} - -=head2 attach_after - - $this->attach_after( $that ); - -Attaches the object at the position just after the -calling object's position. - -=cut - -sub attach_after { - my( $self, $sibling ) = @_; - croak('This method may only be used with the Positional component') if (!$self->positional()); - $sibling->parent( $self->parent() ); - $sibling->move_to( $self->get_column($self->position_column()) + 1 ); -} - -=head2 positional - - if ($object->positional()) { ... } - -Returns true if the object is a DBIx::Class::Positional -object. - -=cut - -sub positional { - my( $self ) = @_; - return $self->isa('DBIx::Class::Positional'); -} - -=head1 PRIVATE METHODS - -These methods are used internally. You should never have the -need to use them. - -=head2 _collection_clause - -This method is provided as an override of the method in -L. This way Positional and Tree::AdjacencyList -may be used together without conflict. Make sure that in -your component list that you load Tree::AdjacencyList before you -load Positional. - -=cut - -sub _collection_clause { - my( $self ) = @_; - return ( - $self->parent_column() => - $self->get_column($self->parent_column()) - ); -} - 1; __END__ diff --git a/lib/DBIx/Class/Tree/AdjacencyList/Positional.pm b/lib/DBIx/Class/Tree/AdjacencyList/Positional.pm new file mode 100644 index 0000000..97e4149 --- /dev/null +++ b/lib/DBIx/Class/Tree/AdjacencyList/Positional.pm @@ -0,0 +1,213 @@ +# vim: ts=8:sw=4:sts=4:et +package DBIx::Class::Tree::AdjacencyList::Positional; +use strict; +use warnings; +use base qw( DBIx::Class ); +use Carp qw( croak ); + +__PACKAGE__->load_components(qw( + Tree::AdjacencyList + Positional +)); + +=head1 NAME + +DBIx::Class::Tree::AdjacencyList::Positional - Glue DBIx::Class::Positional and DBIx::Class::Tree::AdjacencyList together. (EXPERIMENTAL) + +=head1 SYNOPSIS + +Create a table for your tree data. + + CREATE TABLE employees ( + employee_id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_id INTEGER NOT NULL, + position INTEGER NOT NULL, + name TEXT NOT NULL + ); + +In your Schema or DB class add Tree::AdjacencyList::Positional +to the top of the component list. + + __PACKAGE__->load_components(qw( Tree::AdjacencyList::Positional ... )); + +Specify the column that contains the parent ID and position of each row. + + package My::Employee; + __PACKAGE__->parent_column('parent_id'); + __PACAKGE__->position_column('position'); + +This module provides a few extra methods beyond what +L and L +already provide. + + my $parent = $employee->parent(); + $employee->parent( $parent_obj ); + $employee->parent( $parent_id ); + + my $children_rs = $employee->children(); + my @children = $employee->children(); + + $parent->append_child( $child ); + $parent->prepend_child( $child ); + + $this->attach_before( $that ); + $this->attach_after( $that ); + +=head1 DESCRIPTION + +This module provides methods for working with adjacency lists and positional +rows. All of the methods that L and +L provide are available with this module. +If you + +=head1 METHODS + +=head2 parent + + my $parent = $employee->parent(); + $employee->parent( $parent_obj ); + $employee->parent( $parent_id ); + + my $children_rs = $employee->children(); + my @children = $employee->children(); + +This method works exactly like it does in the +DBIx::Class::Tree::AdjacencyList module except that it will +first move the object to the last position of the list, change +the parent ID, then move the object to the last position of +the new list. This ensures the intergrity of the positions. + +=cut + +sub parent { + my( $self, $new_parent ) = @_; + if ($new_parent) { + if (ref($new_parent)) { + $new_parent = $new_parent->id() || 0; + } + return 0 if ($new_parent == ($self->get_column($self->parent_column())||0)); + $self->move_last(); + return 0 if (!$self->next::method( $new_parent )); + $self->set_column( + $self->position_column() => $self->search( {$self->_collection_clause()} )->count() + 1 + ); + $self->update(); + return 1; + } + else { + return $self->next::method(); + } +} + +=head2 children + + my $children_rs = $employee->children(); + my @children = $employee->children(); + +This method works just like it does in the +DBIx::Class::Tree::AdjacencyList module except it +orders the children by there position. + +=cut + +sub children { + my( $self ) = @_; + my $rs = $self->search( + { $self->parent_column() => $self->id() }, + { order_by => $self->position_column() } + ); + return $rs->all() if (wantarray()); + return $rs; +} + +=head2 append_child + + $parent->append_child( $child ); + +Sets the child to have the specified parent and moves the +child to the last position. + +=cut + +sub append_child { + my( $self, $child ) = @_; + $child->parent( $self ); +} + +=head2 prepend_child + + $parent->prepend_child( $child ); + +Sets the child to have the specified parent and moves the +child to the first position. + +=cut + +sub prepend_child { + my( $self, $child ) = @_; + $child->parent( $self ); + $child->move_first(); +} + +=head2 attach_before + + $this->attach_before( $that ); + +Attaches the object at the position just before the +calling object's position. + +=cut + +sub attach_before { + my( $self, $sibling ) = @_; + $sibling->parent( $self->parent() ); + $sibling->move_to( $self->get_column($self->position_column()) ); +} + +=head2 attach_after + + $this->attach_after( $that ); + +Attaches the object at the position just after the +calling object's position. + +=cut + +sub attach_after { + my( $self, $sibling ) = @_; + $sibling->parent( $self->parent() ); + $sibling->move_to( $self->get_column($self->position_column()) + 1 ); +} + +=head1 PRIVATE METHODS + +These methods are used internally. You should never have the +need to use them. + +=head2 _collection_clause + +This method is provided as an override of the method in +L. This method is what provides the +glue between AdjacencyList and Positional. + +=cut + +sub _collection_clause { + my( $self ) = @_; + return ( + $self->parent_column() => + $self->get_column($self->parent_column()) + ); +} + +1; +__END__ + +=head1 AUTHOR + +Aran Clary Deltac + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. + diff --git a/t/01pod.t b/t/01_pod.t similarity index 100% rename from t/01pod.t rename to t/01_pod.t