view release on metacpan or search on metacpan
t/11_mapper/lib/MyTest/Basic/ArtistCompileError.pm
t/11_mapper/lib/MyTest/Basic/GenericAccessorArtist.pm
t/11_mapper/lib/MyTest/CO/Artist.pm
t/12_session/000_array.t
t/12_session/000_basic.t
t/12_session/001_query.t
t/12_session/010_relation_basic.t
t/12_session/011_relation_search.t
t/12_session/012_self_relation.t
t/12_session/013_lazyload.t
t/12_session/014_cascade.t
t/12_session/015_default_condition.t
t/12_session/016_belongs_to_cascade.t
t/12_session/017_default_value.t
t/12_session/018_no_cache.t
t/12_session/019_transaction.t
t/12_session/020_share_object.t
t/12_session/021_validation.t
t/12_session/022_change_checker.t
t/12_session/023_arrayref_obj.t
t/12_session/024_has_one_foreign_key.t
t/12_session/025_differ_prop_name_and_col_name.t
t/12_session/026_init_using_accessor_object.t
lib/DBIx/ObjectMapper/Mapper/Instance.pm view on Meta::CPAN
unless( $self->unit_of_work ) {
my $uow = shift || confess "need UnitOfWork";
$self->{unit_of_work} = $uow;
}
}
elsif( $status_name eq 'detached' ) {
my $class_mapper = $self->instance->__class_mapper__;
for my $prop_name ( $class_mapper->attributes->property_names ) {
my $prop = $class_mapper->attributes->property_info($prop_name);
next unless $prop->type eq 'relation';
if( $prop->{isa}->is_cascade_detach() ) {
if( my $instance = $self->get_val($prop_name) ) {
my @instance
= ref $instance eq 'ARRAY'
? @$instance
: ($instance);
$self->unit_of_work->detach($_) for @instance;
}
}
}
$self->_clear_cache;
}
elsif( $status_name eq 'expired' ) {
my $class_mapper = $self->instance->__class_mapper__;
for my $prop_name ( $class_mapper->attributes->property_names ) {
my $prop = $class_mapper->attributes->property_info($prop_name);
next unless $prop->type eq 'relation';
if( $prop->{isa}->is_cascade_reflesh_expire() ) {
if( my $instance = $self->get_val($prop_name) ) {
my @instance
= ref $instance eq 'ARRAY'
? @$instance
: ($instance);
for ( @instance ) {
my $mapper = $_->__mapper__;
if ( $mapper->is_pending
|| $mapper->is_persistent )
{
lib/DBIx/ObjectMapper/Mapper/Instance.pm view on Meta::CPAN
};
$self->change_status('persistent');
$self->_modify( $new_val );
$self->unit_of_work->_set_cache($self);
$self->initialize;
for my $prop_name ( $class_mapper->attributes->property_names ) {
my $prop = $class_mapper->attributes->property_info($prop_name);
next unless $prop->type eq 'relation';
if( $prop->{isa}->is_cascade_reflesh_expire() ) {
if( my $instance = $self->get_val($prop_name) ) {
my @instance
= ref $instance eq 'ARRAY'
? @$instance
: ($instance);
$_->__mapper__->reflesh for @instance;
}
}
}
}
lib/DBIx/ObjectMapper/Mapper/Instance.pm view on Meta::CPAN
my ( $self ) = @_;
confess 'it need to be "persistent" status.' unless $self->is_persistent;
my $reduce_data = $self->reducing;
my $modified_data = $self->modified_data;
my $uniq_cond = $self->identity_condition;
my $class_mapper = $self->instance->__class_mapper__;
my $result;
try {
my @after_cascade;
for my $prop_name ( $class_mapper->attributes->property_names ) {
my $prop = $class_mapper->attributes->property_info($prop_name);
next unless $prop->type eq 'relation';
if (ref( $prop->{isa} ) eq
'DBIx::ObjectMapper::Relation::BelongsTo' )
{
if ( $prop->{isa}->is_cascade_save_update() ) {
$prop->{isa}->cascade_update($self);
}
if( $modified_data->{$prop_name} ) {
$prop->{isa}->set_val_from_object(
$self,
$self->get_val($prop_name),
);
}
}
elsif ( $prop->{isa}->is_cascade_save_update() ) {
push @after_cascade, $prop;
}
}
my $new_val;
if( keys %$modified_data ) {
my %mod_data;
for ( keys %$modified_data ) {
my $prop = $class_mapper->attributes->property_info($_);
$mod_data{$prop->name} = $modified_data->{$_};
}
$result = $class_mapper->update( \%mod_data, $uniq_cond );
$new_val = DBIx::ObjectMapper::Utils::merge_hashref(
$reduce_data,
$modified_data
);
}
for my $c ( @after_cascade ) {
$c->{isa}->cascade_update( $self );
}
$self->_release_many_to_many_event;
$self->_modify($new_val) if $new_val;
} catch {
$self->change_status('detached');
confess $_[0];
};
$self->{is_modified} = 0;
$self->{modified_data} = +{};
$self->change_status('expired'); # cascade expire if cascade_reflesh_expire
return !$result || $self->instance;
}
sub save {
my ( $self ) = @_;
confess 'it need to be "pending" status.' unless $self->is_pending;
my $class_mapper = $self->instance->__class_mapper__;
try {
my @after_cascade;
for my $prop_name ( $class_mapper->attributes->property_names ) {
my $prop = $class_mapper->attributes->property_info($prop_name);
if ( $prop->type eq 'relation' ) {
if (ref( $prop->{isa} ) eq
'DBIx::ObjectMapper::Relation::BelongsTo' )
{
if ( my $instance = $self->get_val($prop_name) ) {
my @instances
= ref $instance eq 'ARRAY'
? @$instance
: ($instance);
for my $i (@instances) {
if( $prop->{isa}->is_cascade_save_update() ) {
$prop->{isa}->cascade_save( $self, $i );
}
else {
$prop->{isa}->set_val_from_object( $self, $i );
}
}
}
}
elsif( $prop->{isa}->is_cascade_save_update() ) {
push @after_cascade, $prop;
}
}
}
my $reduce_data = $self->reducing;
my $data = { %$reduce_data, %{$class_mapper->default_value} };
my $comp_result = $class_mapper->insert(%$data);
$self->_modify($comp_result);
$self->initialize;
for my $c ( @after_cascade ) {
if ( my $instance = $self->get_val($c->name) ) {
my @instances
= ref $instance eq 'ARRAY'
? @$instance
: ($instance);
for my $i (@instances) {
$c->{isa}->cascade_save( $self, $i );
}
}
}
} catch {
$self->change_status('detached');
confess $_[0];
};
$self->change_status('expired');
lib/DBIx/ObjectMapper/Mapper/Instance.pm view on Meta::CPAN
sub delete {
my $self = shift;
confess 'it need to be "persistent" status.' unless $self->is_persistent;
my $deleted_key = shift || +{};
my $uniq_cond = $self->identity_condition;
my $class_mapper = $self->instance->__class_mapper__;
my $result;
try {
my @after_cascade;
$deleted_key->{$self->primary_cache_key} = 1;
for my $prop_name ( $class_mapper->attributes->property_names ) {
my $prop = $class_mapper->attributes->property_info($prop_name);
if ( $prop->type eq 'relation'
and $prop->{isa}->is_cascade_delete() )
{
if (ref( $prop->{isa} ) eq
'DBIx::ObjectMapper::Relation::BelongsTo' )
{
push @after_cascade, $prop;
}
else {
$self->_cascade_delete($prop, $deleted_key);
}
}
elsif( $prop->is_multi ) {
$prop->{isa}->deleted_parent($self);
}
}
$result = $class_mapper->delete(@$uniq_cond);
for my $c ( @after_cascade ) {
$self->_cascade_delete($c, $deleted_key);
}
} catch {
$self->change_status('detached');
confess $_[0];
};
$self->change_status('detached');
return $result;
}
sub _cascade_delete {
my ( $self, $prop, $deleted_key ) = @_;
$prop->{isa}->cascade_delete($self, $deleted_key);
if ( my $instance = $self->get_val($prop->name) ) {
my @instance
= ref $instance eq 'ARRAY'
? @$instance
: ($instance);
$self->unit_of_work->detach($_) for @instance;
}
}
sub _clear_cache {
lib/DBIx/ObjectMapper/Mapper/Instance.pm view on Meta::CPAN
return unless $prop->type eq 'relation';
if ( $prop->{isa}->type eq 'many_to_many'
and $obj->__mapper__->is_persistent )
{
my $mapper_addr = refaddr($obj);
$self->_regist_many_to_many_event($name, $mapper_addr, 'remove');
}
elsif( $self->is_persistent ) {
if( $prop->{isa}->is_cascade_delete_orphan ) {
$self->unit_of_work->delete($obj);
}
else {
my $rel_val = $prop->{isa}->relation_value($self);
for my $r ( keys %$rel_val ) {
$obj->__mapper__->set_val_trigger( $r => undef );
$obj->__mapper__->set_val( $r => undef );
}
}
$self->unit_of_work->flush if $self->unit_of_work->autoflush;
lib/DBIx/ObjectMapper/Metadata/Table.pm view on Meta::CPAN
}
sub delete {
my $self = shift;
my $query = $self->query_object->delete( $self->_delete_query_callback )
->table( $self->table_name );
$query->where(@_) if @_;
return $query;
}
sub _delete_query_callback { undef } # TODO cascade delete
sub update {
my $self = shift;
my ( $data, $cond ) = @_;
my $query = $self->query_object->update( $self->_update_query_callback )
->table( $self->table_name );
$query->set(%$data) if $data;
$query->where( @$cond ) if $cond;
return $query;
}
lib/DBIx/ObjectMapper/Relation.pm view on Meta::CPAN
sub new {
my ( $class, $rel_class, $option ) = @_;
my $is_multi = $class->initial_is_multi || 0;
my $self = bless +{
name => undef,
rel_class => $rel_class,
option => $option || {},
type => 'relation',
cascade => +{},
is_multi => $is_multi,
table => undef,
via => [],
}, $class;
$self->_init_option;
return $self;
}
sub is_multi { $_[0]->{is_multi} }
sub _init_option {
my $self = shift;
if( my $cascade_option = $self->option->{cascade} ) {
$cascade_option =~ s/\s//g;
my %cascade = map { $_ => 1 } split ',', $cascade_option;
if( $cascade{all} ) {
$self->{cascade}{$_} = 1
for qw(save_update reflesh_expire delete detach);
}
for my $c ( keys %CASCADE_TYPES ) {
$self->{cascade}{$c} = 1 if $cascade{$c};
}
}
if( my $order_by = $self->option->{order_by} ) {
$order_by = [ $order_by ] unless ref $order_by eq 'ARRAY';
$self->{order_by} = $order_by;
}
}
{
no strict 'refs';
my $pkg = __PACKAGE__;
for my $cascade ( keys %CASCADE_TYPES ) {
*{"$pkg\::is_cascade_$cascade"} = sub {
my $self = shift;
return $self->{cascade}{$cascade} || do {
if( $self->is_multi ) {
$CASCADE_TYPES{$cascade}->[1];
}
else {
$CASCADE_TYPES{$cascade}->[0];
}
}
};
}
};
sub mapper {
my $self = shift;
unless( DBIx::ObjectMapper::Mapper->is_initialized($self->rel_class) ) {
confess 'the '
lib/DBIx/ObjectMapper/Relation.pm view on Meta::CPAN
@order_by = map { $rel_mapper->attributes->property($_) }
@{ $rel_mapper->table->primary_key };
}
return $mapper->unit_of_work->search( $self->rel_class )->filter(@$cond)
->order_by(@order_by)->execute->all;
}
sub relation_condition {}
sub cascade_delete {
my $self = shift;
return unless $self->is_cascade_delete;
my $mapper = shift;
my $deleted_key = shift;
for my $child ( $self->_get($mapper) ) {
unless( $deleted_key->{$child->__mapper__->primary_cache_key} ) {
$child->__mapper__->delete($deleted_key);
}
}
}
sub relation_value {
lib/DBIx/ObjectMapper/Relation.pm view on Meta::CPAN
my $rel_val = $self->relation_value($mapper);
my $rel_mapper = $self->mapper;
my @cond;
for my $r ( keys %$rel_val ) {
next unless defined $rel_val->{$r};
push @cond, $rel_mapper->table->c( $r ) == $rel_val->{$r};
}
return @cond;
}
sub cascade_update {
my $self = shift;
my $mapper = shift;
return unless $self->is_cascade_save_update and $mapper->is_modified;
my $uniq_cond = $mapper->relation_condition->{$self->name};
my $modified_data = $mapper->modified_data;
my $class_mapper = $mapper->instance->__class_mapper__;
my $rel_mapper = $self->mapper;
my $fk = $self->foreign_key($class_mapper->table, $rel_mapper->table);
my %foreign_key =
map{ $fk->{refs}->[$_] => $fk->{keys}->[$_] } 0 .. $#{$fk->{keys}};
lib/DBIx/ObjectMapper/Relation.pm view on Meta::CPAN
my $prop = $class_mapper->attributes->property_info( $mkey );
if( $foreign_key{$mkey} ) {
$sets{$foreign_key{$mkey}} = $modified_data->{$mkey};
}
}
return unless keys %sets;
$self->mapper->update( \%sets, $uniq_cond );
}
sub cascade_save {
my $self = shift;
my $mapper = shift;
my $instance = shift;
return unless $self->is_cascade_save_update;
my %sets;
my $rel_val = $self->relation_value($mapper);
for my $r ( keys %$rel_val ) {
$instance->__mapper__->set_val( $r => $rel_val->{$r} );
}
$mapper->unit_of_work->add($instance);
$instance->__mapper__->save;
lib/DBIx/ObjectMapper/Relation/BelongsTo.pm view on Meta::CPAN
my $prop = $class_mapper->attributes->property_info( $prop_name );
next unless $prop->type eq 'column';
if( $foreign_key{$prop->name} ) {
$val{$foreign_key{$prop->name}} = $mapper->get_val( $prop_name );
}
}
return \%val;
}
sub cascade_update { }
sub cascade_save {
my $self = shift;
my $mapper = shift;
my $instance = shift;
return unless $self->is_cascade_save_update;
if( $instance->__mapper__->is_transient ) {
$mapper->unit_of_work->add($instance);
$instance->__mapper__->save;
}
$self->set_val_from_object($mapper, $instance);
}
sub set_val_from_object {
my $self = shift;
lib/DBIx/ObjectMapper/Relation/ManyToMany.pm view on Meta::CPAN
my $cond = $mapper->relation_condition->{$self->name};
my $query = $mapper->unit_of_work->search( $self->rel_class )
->filter(@$cond)
->order_by( map { $attr->p($_) }
@{ $rel_mapper->table->primary_key } );
push @{$query->{join}}, [ $self->assc_table => \@assc_cond ];
return $query->execute->all;
}
sub cascade_save {
my $self = shift;
my $mapper = shift;
my $instance = shift;
return unless $self->is_cascade_save_update;
my $class_mapper = $mapper->instance->__class_mapper__;
my $rel_mapper = $self->mapper;
$mapper->unit_of_work->add($instance);
if( $instance->__mapper__->is_pending ) {
$instance->__mapper__->save;
}
my %values;
lib/DBIx/ObjectMapper/Relation/ManyToMany.pm view on Meta::CPAN
$self->assc_table->get_foreign_key_by_table( $class_mapper->table );
for my $i ( 0 .. $#{$fk2->{keys}} ) {
$values{ $fk2->{keys}->[$i] } = $mapper->get_val( $fk2->{refs}->[$i] );
}
$self->assc_table->insert->values(\%values)->execute;
return $instance;
}
sub cascade_update {
my $self = shift;
my $mapper = shift;
return unless $self->is_cascade_save_update and $mapper->is_modified;
my $uniq_cond = $mapper->relation_condition->{$self->name};
my $modified_data = $mapper->modified_data;
my $class_mapper = $mapper->instance->__class_mapper__;
my $fk =
$self->assc_table->get_foreign_key_by_table( $class_mapper->table );
my %foreign_key =
map{ $fk->{refs}->[$_] => $fk->{keys}->[$_] } 0 .. $#{$fk->{keys}};
lib/DBIx/ObjectMapper/Relation/ManyToMany.pm view on Meta::CPAN
my $prop = $class_mapper->attributes->property_info( $mkey );
if( $foreign_key{$prop->name} ) {
$sets{$foreign_key{$prop->name}} = $modified_data->{$mkey};
}
}
return unless keys %sets;
$self->assc_table->update->set(%sets)->where(@$uniq_cond)->execute;
}
sub cascade_delete {
my $self = shift;
my $mapper = shift;
return unless $self->is_cascade_delete;
my @cond = $self->identity_condition($mapper);
return if !@cond || ( @cond == 1 and !defined $cond[0]->[2] );
$self->assc_table->delete->where(@cond)->execute;
}
sub many_to_many_add {
my $self = shift;
my ($mapper, $instance) = @_;
$self->cascade_save(@_);
}
sub many_to_many_remove {
my $self = shift;
my ($mapper, $instance) = @_;
my $rel_mapper = $self->mapper;
my $uniq_cond = $mapper->relation_condition->{$self->name};
my @cond = @$uniq_cond;
my $fk1 =
t/12_session/010_relation_basic.t view on Meta::CPAN
constructor => +{ auto => 1 },
accessors => +{ auto => 1 },
attributes => +{
properties => +{
children => +{
isa => $mapper->relation(
has_many => 'MyTest010::Child',
{
order_by =>
$mapper->metadata->t('child')->c('id')->desc,
cascade => 'all,delete_orphan',
}
),
}
}
}
);
ok $mapper->maps(
$mapper->metadata->t('child') => 'MyTest010::Child',
constructor => +{ auto => 1 },
t/12_session/012_self_relation.t view on Meta::CPAN
ok $mapper->maps(
$bbs => 'MyTest12::BBS2',
constructor => { auto => 1 },
accessors => { auto => 1 },
attributes => {
properties => {
parent => {
isa => $mapper->relation(
'belongs_to' => 'MyTest12::BBS2',
{ cascade => 'all' },
),
},
children => {
isa => $mapper->relation(
'has_many' => 'MyTest12::BBS2',
{ cascade => 'all' },
),
}
}
}
);
subtest 'cascade' => sub {
$mapper->metadata->t('bbs')->delete->execute;
my $session = $mapper->begin_session( autocommit => 0 );
my $attr = $mapper->attribute('MyTest12::BBS2');
# cascade_save
my $bbs = MyTest12::BBS2->new( comment => 'cascade_save' );
my @children = (
map{ MyTest12::BBS2->new( comment => 'cascade_save child' . $_ ) }
( 1 .. 5 )
);
$bbs->children(\@children);
$session->add($bbs);
is $session->search('MyTest12::BBS2')->count, 6;
# cascade_update
$bbs->id(100);
ok my $parent = $session->get( 'MyTest12::BBS2' => 100 );
is @{$parent->children}, 5;
# orphan
my $orphan = shift @{$parent->children};
is @{$parent->children}, 4;
is $session->search('MyTest12::BBS2')->filter(
$attr->p('parent_id') == undef
)->count, 2;
# add orphan
push @{$parent->children}, $orphan;
is @{$parent->children}, 5;
is $session->search('MyTest12::BBS2')->filter(
$attr->p('parent_id') == undef
)->count, 1;
# cascade delete
$session->delete($parent);
is $session->search('MyTest12::BBS2')->count, 0;
done_testing;
};
subtest 'many_to_one_cascade_save' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
my $attr = $mapper->attribute('MyTest12::BBS2');
# save
my $child1 = MyTest12::BBS2->new( comment => 'many_to_one child' );
my $parent = MyTest12::BBS2->new( comment => 'many_to_one parent' );
$child1->parent($parent);
$session->add($child1);
is $session->search('MyTest12::BBS2')->count, 2;
t/12_session/014_cascade.t view on Meta::CPAN
use FindBin;
use lib File::Spec->catfile($FindBin::Bin, 'lib');
use MyTest11;
MyTest11->setup_default_data;
MyTest11->mapping_with_foreign_key;
my $mapper = MyTest11->mapper;
subtest 'cascade_detach' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
ok my $artist = $session->get( 'MyTest11::Artist' => 1 );
for my $cd ( @{$artist->cds} ) {
ok $cd;
ok $cd->linernote;
for my $track ( @{$cd->tracks} ) {
ok $track;
}
}
$session->detach($artist);
t/12_session/014_cascade.t view on Meta::CPAN
ok $cd->__mapper__->is_detached;
ok $cd->linernote->__mapper__->is_detached;
for my $track ( @{$cd->tracks} ) {
ok $track->__mapper__->is_detached;
}
}
done_testing;
};
subtest 'cascade_delete' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
my $cd = $mapper->metadata->t('cd');
my $artist = $session->get( 'MyTest11::Artist' => 1 );
$session->delete($artist);
$session->flush;
# check
ok !$session->get( 'MyTest11::Artist' => 1 );
is $session->search('MyTest11::Cd')->count, 0;
is $session->search('MyTest11::Track')->count, 0;
is $session->search('MyTest11::Linernote')->count, 0;
done_testing;
};
subtest 'cascade_update' => sub {
my $session = $mapper->begin_session;
my $cd2 = $session->get( 'MyTest11::Cd' => 2 );
my @cd2_tracks = @{$cd2->tracks};
$cd2->id(100);
$session->flush;
is $cd2->__mapper__->status, 'expired';
is $cd2->id, 100; # not reflesh
# check
t/12_session/014_cascade.t view on Meta::CPAN
ok my @cd100_tracks = @{$cd100->tracks};
ok @cd2_tracks == @cd100_tracks;
for my $i ( 0 .. $#cd2_tracks ) {
is $cd2_tracks[$i]->title, $cd100_tracks[$i]->title;
is $cd2_tracks[$i]->track_no, $cd100_tracks[$i]->track_no;
}
done_testing;
};
subtest 'cascade_save' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
ok my $jimi = MyTest11::Artist->new( name => 'Jimi Hendrix' );
is_deeply $jimi->cds, [];
$session->add($jimi);
ok my $first_album = MyTest11::Cd->new( title => 'Are You Experienced' );
push @{$jimi->cds}, $first_album;
my @bulk_tracks = (
'Purple Haze',
'Manic Depression',
t/12_session/016_belongs_to_cascade.t view on Meta::CPAN
ok $mapper->maps(
$mapper->metadata->t('child') => 'MyTest016::Child',
constructor => +{ auto => 1 },
accessors => +{ auto => 1 },
attributes => +{
properties => +{
parent => +{
isa => $mapper->relation(
belongs_to => 'MyTest016::Parent',
{ cascade => 'save_update,delete' }
)
}
}
},
);
{
my $session = $mapper->begin_session;
my @child = map{ MyTest016::Child->new( name => 'child' . $_ ) } 1 .. 5;
my $parent = MyTest016::Parent->new( id => 1, name => 'parent1' );
t/12_session/016_belongs_to_cascade.t view on Meta::CPAN
ok $mapper->maps(
$mapper->metadata->t('parent') => 'MyTest016::Parent2',
constructor => +{ auto => 1 },
accessors => +{ auto => 1 },
attributes => +{
properties => +{
children => +{
isa => $mapper->relation(
has_many => 'MyTest016::Child2',
{ cascade => 'all' },
),
}
}
}
);
ok $mapper->maps(
$mapper->metadata->t('child') => 'MyTest016::Child2',
constructor => +{ auto => 1 },
accessors => +{ auto => 1 },
attributes => +{
properties => +{
parent => +{
isa => $mapper->relation(
belongs_to => 'MyTest016::Parent2',
{ cascade => 'save_update,delete' }
)
}
}
},
);
{
my $session = $mapper->begin_session;
my @child = map{ MyTest016::Child2->new( name => 'child' . $_ ) } 11 .. 15;
my $parent = MyTest016::Parent2->new( id => 3, name => 'parent3' );
t/12_session/021_validation.t view on Meta::CPAN
1;
};
my $parent_mapper = $mapper->maps(
$mapper->metadata->t('parent') => 'MyTest21::Parent',
attributes => {
properties => {
children => {
isa => $mapper->relation(
has_many => 'MyTest21::Child',
{ cascade => 'save_update' }
),
validation => 1,
},
has_one => {
isa => $mapper->relation(
has_one => 'MyTest21::HasOne',
{ cascade => 'save_update' }
),
validation => 1,
},
id => { validation => 1 },
name => { validation => 1 },
}
}
);
ok $parent_mapper->attributes->property('children')->is_cascade_save_update, 'only cascade save_update';
ok $parent_mapper->attributes->property('children')->validation, 'set validation option';
$mapper->maps(
$mapper->metadata->t('child') => 'MyTest21::Child',
attributes => {
properties => {
parent => {
isa => $mapper->relation(
belongs_to => 'MyTest21::Parent',
{ cascade => 'save_update' }
),
validation => 1,
},
}
}
);
$mapper->maps(
$mapper->metadata->t('has_one') => 'MyTest21::HasOne',
t/12_session/100_many_to_many.t view on Meta::CPAN
ok $mapper->maps(
$left => 'MyTest14::Parent',
constructor => { auto => 1 },
accessors => { auto => 1 },
attributes => {
properties => {
children => {
isa => $mapper->relation(
'many_to_many' => $association => 'MyTest14::Child',
{ cascade => 'all'}
),
validation => 1,
}
}
}
);
ok $mapper->maps(
$right => 'MyTest14::Child',
constructor => { auto => 1 },
accessors => { auto => 1 },
attributes => {
properties => {
parents => {
isa => $mapper->relation(
'many_to_many' => $association => 'MyTest14::Parent',
{ cascade => 'all' }
)
}
}
}
);
subtest 'cascade_save' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
ok my $parent = MyTest14::Parent->new( id => 1 );
dies_ok{ $parent->children('hoge') } 'validation fail';
dies_ok{ $parent->children([qw(a b c)]) } 'validation fail';
my @children = map { MyTest14::Child->new( id => $_ ) } ( 1 .. 5 );
ok $parent->children(\@children);
$session->add($parent);
t/12_session/100_many_to_many.t view on Meta::CPAN
$session->flush;
$session->commit;
# check
my $check_parent = $session->get( 'MyTest14::Parent' => 1 );
is @{$check_parent->children}, 5;
done_testing;
};
subtest 'cascade_update' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
ok my $parent = $session->get( 'MyTest14::Parent' => 1 );
$parent->id(10);
$session->commit;
# check
ok my $check_parent = $session->get( 'MyTest14::Parent' => 10 );
is @{$check_parent->children}, 5;
done_testing;
t/12_session/100_many_to_many.t view on Meta::CPAN
shift @{$p->children};
$session->commit;
# check
ok my $check = $session->get( 'MyTest14::Parent' => 10 );
is scalar(@{$check->children}), 5;
done_testing;
};
subtest 'cascade_delete' => sub {
my $session = $mapper->begin_session( autocommit => 0 );
ok my $p = $session->get( 'MyTest14::Parent' => 10 );
my @child_ids = map { $_->id } @{$p->children};
$session->delete($p);
$session->commit;
# check
ok !$session->get( 'MyTest14::Parent' => 10 );
is $association->select->where( $association->c('left_id') == 10 )->count, 0;
for my $cid ( @child_ids ) {
t/12_session/lib/MyTest11.pm view on Meta::CPAN
sub mapping_with_foreign_key {
my $artist_mapper = $mapper->maps(
$artist => 'MyTest11::Artist',
constructor => { auto => 1 },
accessors => { auto => 1 },
attributes => {
properties => {
cds => +{
isa => $mapper->relation(
has_many => 'MyTest11::Cd',
{ cascade => 'all' },
),
}
}
}
);
my $cd_mapper = $mapper->maps(
$cd => 'MyTest11::Cd',
constructor => { auto => 1 },
accessors => { auto => 1 },
attributes => {
properties => {
artist => +{
isa => $mapper->relation( belongs_to => 'MyTest11::Artist' )
},
tracks => +{
isa => $mapper->relation(
has_many => 'MyTest11::Track',
{ cascade => 'all' },
),
},
linernote => +{
isa =>
$mapper->relation(
has_one => 'MyTest11::Linernote',
{ cascade => 'all' },
),
}
}
}
);
my $track_mapper = $mapper->maps(
$track => 'MyTest11::Track',
constructor => { auto => 1 },
accessors => { auto => 1 },
t/21_example/shopping_cart.t view on Meta::CPAN
);
$mapper->maps(
$shopping_cart => 'MapperExample::ShoppingCart',
attributes => {
properties => {
items => {
isa => $mapper->relation(
many_to_many => $shopping_cart_item
=> 'MapperExample::Product',
{ cascade => 'save_update,delete' },
),
}
}
}
);
# ã¡ã¿ãã¼ã¿ããproductã¸ã¤ã³ãµã¼ã
$product->insert( prodkey => 'ABC-1', title => 'title1', price => 100 )->execute;
$product->insert( prodkey => 'ABC-2', title => 'title2', price => 200 )->execute;
$product->insert( prodkey => 'ABC-3', title => 'title3', price => 300 )->execute;