DBICx-MaterializedPath

 view release on metacpan or  search on metacpan

lib/DBICx/MaterializedPath.pm  view on Meta::CPAN

    my $self = shift;
    my $path_column = $self->path_column || "";
    my $separator = quotemeta( $self->path_separator );
    split($separator, $self->$path_column || "");
}

sub root_node :method {
    my $self = shift;
    my ( $root_id ) = $self->_nodelist;
    $self->result_source->resultset->find($root_id);
}

# Note caveat, instructions about children method.

# How can order_by get into this mix?
sub grandchildren {
    my $self = shift;
    
    my $path_separator = $self->path_separator;
    my $path_column    = $self->path_column;
    my $id             = $self->id;

    # Example: 1/2/3
    # to find descendants of 1, use LIKE "1/%"
    # to find descendants of 2, use LIKE "%/2/%"
    my $like_if_root  = "${id}${path_separator}\%";
    my $like_not_root = "\%${path_separator}${id}${path_separator}\%";

    my @grandkids = $self->result_source->resultset->search(
        {
            -or => [
                $path_column => { 'like', $like_if_root  },
                $path_column => { 'like', $like_not_root },
            ]
        },
        {
            order_by => \"LENGTH($path_column)"
        },
    );
    return @grandkids;
}

sub set_materialized_path :method {
    my $self = shift;
    my $parent_column = $self->parent_column;
    my $path_column = $self->path_column;
    my @path_parts = map { $_->id } $self->_compute_ancestors;
    push @path_parts, $self->id;
    my $materialized_path = join( $self->path_separator, @path_parts );
    $self->$path_column( $materialized_path );
    return $materialized_path; # For good measure.
}

sub insert :method {
    my $self = shift;
    $self->next::method(@_);
    $self->set_materialized_path;
    $self->update;
}

sub update :method {
    my $self = shift;
    my %to_update = $self->get_dirty_columns;
    my $parent_column = $self->parent_column;
    $self->next::method(@_);
    return $self unless $to_update{$parent_column};
    # This should be configurable as a transaction I think. 321
    $self->set_materialized_path;
    for my $descendant ( $self->grandchildren )
    {
        $descendant->set_materialized_path;
        $descendant->update;
    }
    return $self;
}

# Previous and next support here.

sub siblings :method {
    my $self = shift;
    my $parent_column = $self->parent_column;
    my $sort = [ $self->_sibling_order || $self->primary_columns ];
    $self->result_source
        ->resultset
        ->search({ $parent_column => $self->$parent_column },
                 { order_by => $sort });
} 

1;

__END__

=pod

=head1 NAME

DBICx::MaterializedPath - L<DBIx::Class> plugin for automatically tracking lineage paths in simple data trees.

=head1 PREFER

Please see L<DBIx::Class::Tree::Mobius>, L<DBIx::Class::Graph>, and L<DBIx::Class::Tree> instead of this experimental package.

=head1 SYNOPSIS

We need a table, or tables, which represents a tree.

 CREATE TABLE tree_data (
    id INTEGER PRIMARY KEY NOT NULL,
    parent INT(10),
    content TEXT NOT NULL,
    path VARCHAR(255),
    created DATETIME(19) NOT NULL
 );
 
 CREATE INDEX tree_data_idx_parent ON tree_data (parent);

In your L<DBIx::Class> add this to your componentsE<ndash>

 use warnings;
 use strict;
 use parent qw( DBIx::Class );



( run in 0.887 second using v1.01-cache-2.11-cpan-39bf76dae61 )