From 454db15e55f697bb4c64b52d1d9403a30361bede Mon Sep 17 00:00:00 2001 From: Zbigniew Lukasiak Date: Wed, 10 Jun 2009 22:55:15 +0200 Subject: [PATCH] Relating an unrelated record with composed pk --- lib/DBIx/Class/ResultSet/RecursiveUpdate.pm | 51 ++++++++++---------- t/lib/RunTests.pm | 23 +++++++-- t/var/dvdzbr.db | Bin 37888 -> 37888 bytes 3 files changed, 45 insertions(+), 29 deletions(-) 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 5a07a70dbcebd4559d5904df0f966ca24beec97d..360cb608b934b43c7c0871489874de929a51af2d 100644 GIT binary patch delta 1018 zcmaiyT}V_x6vywKbMM{VyXx+Gciqj8>z1ZQD!D2cWho_Cl9ouB1!b_<`u(+j?P_ii zA(lCF-ctxdkf6NKqh<6^J>-Ku^kPBvmipL(2{n7`!Ns6q=Eq^?e`e17XC@cORo0KX-NAXkb59U;S zSpvL(d6aN&k#+a$47kFixkpD+h9~|~K z1qTNG^{rh&*{+zPc(yEgEVy6ONQsPnnlDWjHLwXDj~HKU47LxH1WLnw9-O$~S!6AVl+T&2;u;H4w)E5=tA>8Ad6)@l(Jc209zywSfy6*yh*W?()BO|E58oY_wac|0VzlXsUez$<4XO9hHk z+7w{ZP%FNI!zCtIVeA}J-O`2t8-{xR3+S4ZFD5!AiYk9K5w--_GSsGTkdkPov2$rU ziO_DGI+9OlKhj8#6jSK{mR#+`)iEcA9;84K9mMf)CRVjLr2`=v#sX|7bO`GM-FyCP z1#Y+9*J*>rt7+ox%E8tfox$)xKku2R8f&VXYTB5D`p8YfWORf&2vaZ`>LSd7-$OHm zS@}VQlBb8+aIw9QFctNVIl}CCz1eSk?x;*6|41*DV!)EHaP$sg$v8Fpgs>Dmag=-L zz!e%G%*pSSj;qZV33C}VGV7LEOl7J3lGmiz;s4|)%=K5i%MqsSa)h}}N0^5@()k++ CCk;jb delta 960 zcmah{TS!z<6utNCJJ*>poza7?U;A5~LGi1yTLf?Q89Dw$-=#oJpEsS;sq~ z+GmnQ^N&;Q>+0U*co=n>Y!M)uKqpu%8`LUaQ&*BFIR$9UWEVx6HYITUX>yY@%&fT0 z4;^bfyeL;?!kb6Z9yvwirrQT6l~FDHvCa%GC-`jJ(owj`#mX0 z0zs73=8nNMq(u4Twk^HrNicAsc;SVrx3TDxBPDDRKEp5g4j*BzX^ZL{2eOZZ$7nzl zHQEgfQjy6Us8JDUDa}ffE1uzTN_2HF%%pLbm*ELoa@8@+qT+*P472HJPoIoAvNdNv z4fWW_aac>`y;_F3RPT+T3vmSu^LS~c=W2P9*5mFl%%_Vb{ZsL>QCbmTMbW2!1w(n6 zvo}Np$CgE9JyUO%mIYW=^c9O>SO11Va){drh@zg`6k%0>RYhO@4MKU2QpgU4^CSBh zCerZHLkv9>=x>*X^q5RZms)7H&q)6Jp^$*b=vGfO<<=Rc1Aa`QcxqypN@bq5J-05M z)*A2H(GX-cnMBO$u5W1Z^>kh1Pjr4&VP17%BNmYT`c;O7WbijLJViJCtqf1o5C1)e zMf@PQWNF7@nr!N1SVH#ZF@|2cQtMO}nzQ(