From: Zbigniew Lukasiak Date: Wed, 10 Jun 2009 20:55:15 +0000 (+0200) Subject: Relating an unrelated record with composed pk X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fp5-DBIx-Class-ResultSet-RecursiveUpdate;a=commitdiff_plain;h=454db15e55f697bb4c64b52d1d9403a30361bede Relating an unrelated record with composed pk --- diff --git a/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm b/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm index b4ba9b8..fcbad3b 100644 --- a/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm +++ b/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm @@ -22,7 +22,8 @@ use Scalar::Util qw( blessed ); sub recursive_update { my %params = @_; - my ( $self, $updates, $fixed_fields, $object ) = @params{ qw/resultset updates fixed_fields object/ }; + my ( $self, $updates, $fixed_fields, $object, $resolved ) = @params{ qw/resultset updates fixed_fields object resolved/ }; + $resolved ||= {}; # warn 'entering: ' . $self->result_source->from(); carp 'fixed fields needs to be an array ref' if $fixed_fields && ref($fixed_fields) ne 'ARRAY'; my %fixed_fields; @@ -30,6 +31,20 @@ sub recursive_update { if ( blessed($updates) && $updates->isa('DBIx::Class::Row') ) { return $updates; } + if ( $updates->{id} ){ + $object = $self->find( $updates->{id}, { key => 'primary' } ); + } + my @missing = + grep { !exists $updates->{$_} && !exists $fixed_fields{$_} } $self->result_source->primary_columns; + if ( !$object && !scalar @missing ) { + $object = $self->find( $updates, { key => 'primary' } ); + } + @missing = + grep { !exists $resolved->{$_} } @missing; + if ( !$object && !scalar @missing ) { + $object = $self->find( \%{ %$updates, %$resolved }, { key => 'primary' } ); + } + $object ||= $self->new( {} ); # warn Dumper( $updates ); use Data::Dumper; # direct column accessors my %columns; @@ -43,22 +58,12 @@ sub recursive_update { my %post_updates; my %other_methods; my %columns_by_accessor = _get_columns_by_accessor( $self ); +# warn 'resolved: ' . Dumper( $resolved ); + $updates = { %$updates, %$resolved }; +# warn 'updates: ' . Dumper( $updates ); use Data::Dumper; +# warn 'columns: ' . Dumper( \%columns_by_accessor ); for my $name ( keys %$updates ) { my $source = $self->result_source; - if( $name eq 'id' -# && scalar @{$source->primary_columns} == 1 - && !$source->has_column( 'id' ) - ){ - my @ids = ( $updates->{id} ); - if( ref $updates->{id} ){ - @ids = @{ $updates->{id} }; - } - my $i = 0; - for my $key ( $source->primary_columns ){ - $columns{ $key } = $ids[ $i++ ]; - } - next; - } if ( $columns_by_accessor{$name} && !( $source->has_relationship($name) && ref( $updates->{$name} ) ) ) @@ -85,12 +90,6 @@ sub recursive_update { } # warn 'other: ' . Dumper( \%other_methods ); use Data::Dumper; - my @missing = - grep { !exists $columns{$_} && !exists $fixed_fields{$_} } $self->result_source->primary_columns; - if ( !$object && !scalar @missing ) { - $object = $self->find( \%columns, { key => 'primary' } ); - } - $object ||= $self->new( {} ); # first update columns and other accessors - so that later related records can be found for my $name ( keys %columns ) { $object->$name( $columns{$name} ); @@ -105,8 +104,10 @@ sub recursive_update { # $self->_delete_empty_auto_increment($object); # don't allow insert to recurse to related objects - we do the recursion ourselves # $object->{_rel_in_storage} = 1; + $object->update_or_insert; + # updating many_to_many for my $name ( keys %$updates ) { next if exists $columns{$name}; @@ -171,20 +172,18 @@ sub _update_relation { } # warn 'resolved: ' . Dumper( $resolved ); use Data::Dumper; - $resolved = undef + $resolved = {} if defined $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION && $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION == $resolved; if ( ref $updates->{$name} eq 'ARRAY' ) { for my $sub_updates ( @{ $updates->{$name} } ) { - $sub_updates = { %$sub_updates, %$resolved } if $resolved && ref( $sub_updates ) eq 'HASH'; my $sub_object = - recursive_update( resultset => $related_result, updates => $sub_updates ); + recursive_update( resultset => $related_result, updates => $sub_updates, resolved => $resolved ); } } else { my $sub_updates = $updates->{$name}; my $sub_object; if( ref $sub_updates ){ - $sub_updates = { %$sub_updates, %$resolved } if $resolved && ref( $sub_updates ) eq 'HASH'; # for might_have relationship if( $info->{attrs}{accessor} eq 'single' && defined $object->$name ){ $sub_object = recursive_update( @@ -195,7 +194,7 @@ sub _update_relation { } else{ $sub_object = - recursive_update( resultset => $related_result, updates => $sub_updates ); + recursive_update( resultset => $related_result, updates => $sub_updates, resolved => $resolved ); } } elsif( ! ref $sub_updates ){ diff --git a/t/lib/RunTests.pm b/t/lib/RunTests.pm index b5f447d..93255b6 100644 --- a/t/lib/RunTests.pm +++ b/t/lib/RunTests.pm @@ -4,7 +4,7 @@ use Exporter 'import'; # gives you Exporter's import() method directly @EXPORT = qw(run_tests); use strict; use Test::More; - +use DBIx::Class::ResultSet::RecursiveUpdate; sub run_tests{ my $schema = shift; @@ -106,6 +106,17 @@ sub run_tests{ is ( $dvd_updated->tags->count, 0, 'Tags deleted' ); is ( $dvd_updated->liner_notes->notes, 'test note changed', 'might_have record changed' ); + $new_dvd->update( { name => 'New Test Name' } ); + $updates = { + id => $new_dvd->dvd_id, # id instead of dvd_id + like_has_many => [ + { dvd_name => $dvd->name, key2 => 1 } + ], + }; + my $dvd_updated = $dvd_rs->recursive_update( $updates ); + ok ( $schema->resultset( 'Twokeys' )->find( { dvd_name => 'New Test Name', key2 => 1 } ), 'Twokeys updated' ); + ok ( !$schema->resultset( 'Twokeys' )->find( { dvd_name => $dvd->name, key2 => 1 } ), 'Twokeys updated' ); + # repeatable $updates = { @@ -140,13 +151,19 @@ sub run_tests{ street => "101 Main Street", city => "Podunk", state => "New York" - } + }, + owned_dvds =>[ + { + id => 1, + }, + ] }; $user = $user_rs->recursive_update( $updates ); $user = $user_rs->recursive_update( $updates ); is( $schema->resultset( 'Address' )->search({ user_id => $user->id })->count, 1, 'the right number of addresses' ); - + $dvd = $dvd_rs->find( 1 ); + is( $dvd->get_column( 'owner' ), $user->id, 'foreign key set' ); # $updates = { # name => 'Test name 1', diff --git a/t/var/dvdzbr.db b/t/var/dvdzbr.db index 5a07a70..360cb60 100644 Binary files a/t/var/dvdzbr.db and b/t/var/dvdzbr.db differ