Alzabo

 view release on metacpan or  search on metacpan

lib/Alzabo/Runtime/Row.pm  view on Meta::CPAN

package Alzabo::Runtime::Row;

use strict;
use vars qw($VERSION);

use Alzabo;

use Alzabo::Exceptions ( abbr => [ qw( logic_exception no_such_row_exception
                                       params_exception storable_exception ) ] );

use Alzabo::Runtime;
use Alzabo::Runtime::RowState::Deleted;
use Alzabo::Runtime::RowState::Live;
use Alzabo::Runtime::RowState::Potential;
use Alzabo::Utils;

use Params::Validate qw( validate validate_with UNDEF SCALAR HASHREF BOOLEAN );
Params::Validate::validation_options
    ( on_fail => sub { params_exception join '', @_ } );

use Storable ();

$VERSION = 2.0;

BEGIN
{
    no strict 'refs';
    foreach my $meth ( qw( select select_hash update refresh delete
                           id_as_string is_live is_potential is_deleted ) )
    {
        *{ __PACKAGE__ . "::$meth" } =
            sub { my $s = shift;
                  $s->{state}->$meth( $s, @_ ) };
    }
}

use constant NEW_SPEC => { table => { isa => 'Alzabo::Runtime::Table' },
                           pk    => { type => SCALAR | HASHREF,
                                      optional => 1,
                                    },
                           prefetch => { type => UNDEF | HASHREF,
                                         optional => 1,
                                       },
                           state => { type => SCALAR,
                                      default => 'Alzabo::Runtime::RowState::Live',
                                    },
                           potential_row => { isa => 'Alzabo::Runtime::Row',
                                              optional => 1,
                                            },
                           values => { type => HASHREF,
                                       default => {},
                                     },
                           no_cache => { type => BOOLEAN, default => 0 },
                         };

sub new
{
    my $proto = shift;
    my $class = ref $proto || $proto;

    my %p =
        validate( @_, NEW_SPEC );

    my $self = $p{potential_row} ? $p{potential_row} : {};

    bless $self, $class;

    $self->{table} = $p{table};
    $self->{state} = $p{state};

    $self->{state}->_init($self, @_) or return;

    return $self;
}

sub table
{
    my $self = shift;

    return $self->{table};
}

sub schema
{
    my $self = shift;

    return $self->table->schema;
}

sub set_state { $_[0]->{state} = $_[1] };

use constant ROWS_BY_FOREIGN_KEY_SPEC => { foreign_key => { isa => 'Alzabo::ForeignKey' } };

sub rows_by_foreign_key
{
    my $self = shift;
    my %p = validate_with( params => \@_,
                           spec   => ROWS_BY_FOREIGN_KEY_SPEC,
                           allow_extra => 1,
                         );

    my $fk = delete $p{foreign_key};

    if ($p{where})
    {
        $p{where} = [ $p{where} ] unless Alzabo::Utils::is_arrayref( $p{where}[0] );
    }

    push @{ $p{where} },
        map { [ $_->[1], '=', $self->select( $_->[0]->name ) ] } $fk->column_pairs;

    # if the relationship is not 1..n, then only one row can be
    # returned (or referential integrity has been hosed in the
    # database).
    return $fk->is_one_to_many ? $fk->table_to->rows_where(%p) : $fk->table_to->one_row(%p);
}

# class method
sub id_as_string_ext
{
    my $class = shift;
    my %p = @_;
    my $id_hash = $class->_make_id_hash(%p);

    local $^W; # weirdly, enough there are code paths that can
    # lead here that'd lead to $id_hash having some
    # values that are undef
    return join ';:;_;:;', ( $p{table}->schema->name,
                             $p{table}->name,
                             map { $_, $id_hash->{$_} } sort keys %$id_hash );
}

sub _make_id_hash
{
    my $self = shift;
    my %p = @_;

    return $p{pk} if ref $p{pk};

    return { ($p{table}->primary_key)[0]->name => $p{pk} };
}

sub _update_pk_hash
{
    my $self = shift;

    my @pk = keys %{ $self->{pk} };

    @{ $self->{pk} }{ @pk } = @{ $self->{data} }{ @pk };

    delete $self->{id_string};
}

sub make_live
{
    my $self = shift;



( run in 0.618 second using v1.01-cache-2.11-cpan-5a3173703d6 )