From: zby Date: Mon, 2 Feb 2009 16:13:45 +0000 (+0000) Subject: got rid of the requirement to add id => undef X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fp5-DBIx-Class-ResultSet-RecursiveUpdate;a=commitdiff_plain;h=5460c3fd3d2063eb55dd8a72bf3335952f1950b7 got rid of the requirement to add id => undef --- diff --git a/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm b/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm index 3929e49..42dec8d 100644 --- a/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm +++ b/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm @@ -11,64 +11,74 @@ use base qw(DBIx::Class::ResultSet); sub recursive_update { my( $self, $updates, $fixed_fields ) = @_; +# warn 'entering: ' . $self->result_source->from(); if( blessed( $updates ) && $updates->isa( 'DBIx::Class::Row' ) ){ return $updates; } + my $object; +# warn 'fixed_fields: ' . Dumper( $fixed_fields ); use Data::Dumper; + if( $fixed_fields ){ + carp if !( ref( $fixed_fields ) eq 'HASH' ); + $updates = { %$updates, %$fixed_fields }; + } my %columns; - for my $name ( keys %$updates ){ + for my $name ( keys %$updates ){ if( $self->is_for_column( $name, $updates->{$name} ) ){ $columns{$name} = $updates->{$name}; } } - my $object; -# warn 'cond: ' . Dumper( $self->{cond} ); use Data::Dumper; -# warn 'where: ' . Dumper( $self->{attrs}{where} ); use Data::Dumper; - my @missing = grep { !exists $updates->{$_} && !exists $fixed_fields->{$_} } $self->result_source->primary_columns; - if( defined $self->{cond} && $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION == $self->{cond} ){ - $self->{cond} = undef; - $self->{attrs}{where} = undef; - if( ! scalar @missing ){ - $object = $self->find( \%columns, { key => 'primary' } ); - } - } - else{ +# warn 'columns: ' . Dumper( \%columns ); use Data::Dumper; + my @missing = grep { !exists $columns{$_} } $self->result_source->primary_columns; + if( ! 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( $updates->{$name} ); + $object->$name( $updates->{$name} ); } for my $name ( keys %$updates ){ - if($object->can($name) && !$self->is_for_column( $name, $updates->{$name} ) ){ - + next if exists $columns{ $name }; + if( + #$object->can($name) + $object->result_source->has_relationship($name) + && !$self->is_for_column( $object, $name, $updates->{$name} ) + ){ # updating relations that that should be done before the row is inserted into the database # like belongs_to my $info = $object->result_source->relationship_info( $name ); - if( $info and not $info->{attrs}{accessor} eq 'multi' + if( $info #and not $info->{attrs}{accessor} eq 'multi' and _master_relation_cond( $object->result_source, $info->{cond}, $self->_get_pk_for_related( $name ) ) ){ - my $related_result = $object->related_resultset( $name ); + my $related_result = $self->related_resultset( $name )->result_source->resultset; my $resolved = $self->result_source->resolve_condition( $info->{cond}, $name, $object ); # warn 'resolved: ' . Dumper( $resolved ); use Data::Dumper; - my $sub_object = $related_result->recursive_update( $updates->{$name} ); - $object->set_from_related( $name, $sub_object ); + $resolved = undef if $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION == $resolved; + if( ref $updates->{$name} eq 'ARRAY' ){ + for my $sub_updates ( @{$updates->{$name}} ) { + my $sub_object = $related_result->recursive_update( $sub_updates, $resolved ); + } + } + else { + my $sub_object = $related_result->recursive_update( $updates->{$name}, $resolved ); + $object->set_from_related( $name, $sub_object ); + } } } } $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; -# warn Dumper( $object->{_column_data} ); $object->update_or_insert; # updating relations that can be done only after the row is inserted into the database # like has_many and many_to_many for my $name ( keys %$updates ){ + next if exists $columns{ $name }; my $value = $updates->{$name}; # many to many case if( $self->is_m2m( $name ) ) { @@ -88,15 +98,22 @@ sub recursive_update { } elsif( $object->result_source->has_relationship($name) ){ my $info = $object->result_source->relationship_info( $name ); + next if ( _master_relation_cond( $object->result_source, $info->{cond}, $self->_get_pk_for_related( $name ) ) ); # has many case (and similar) + my $resolved = $self->result_source->resolve_condition( + $info->{cond}, $name, $object + ); +# warn 'resolved: ' . Dumper( $resolved ); use Data::Dumper; + $resolved = undef if $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION == $resolved; + my $related_result = $self->related_resultset( $name )->result_source->resultset; if( ref $updates->{$name} eq 'ARRAY' ){ for my $sub_updates ( @{$updates->{$name}} ) { - my $sub_object = $object->search_related( $name )->recursive_update( $sub_updates ); + my $sub_object = $related_result->recursive_update( $sub_updates, $resolved ); } } # might_have and has_one case - elsif ( ! _master_relation_cond( $object->result_source, $info->{cond}, $self->_get_pk_for_related( $name ) ) ){ - my $sub_object = $object->search_related( $name )->recursive_update( $value ); + else{ + my $sub_object = $related_result->recursive_update( $value, $resolved ); #$object->set_from_related( $name, $sub_object ); } } @@ -166,7 +183,6 @@ sub _delete_empty_auto_increment { sub _get_pk_for_related { my ( $self, $relation ) = @_; - my $result_source; if( $self->result_source->has_relationship( $relation ) ){ $result_source = $self->result_source->related_source( $relation ); @@ -201,7 +217,6 @@ sub _master_relation_cond { return; } - 1; # Magic true value required at end of module __END__ diff --git a/t/lib/DBSchema/Result/Dvd.pm b/t/lib/DBSchema/Result/Dvd.pm index f761f76..e791b76 100644 --- a/t/lib/DBSchema/Result/Dvd.pm +++ b/t/lib/DBSchema/Result/Dvd.pm @@ -40,19 +40,25 @@ __PACKAGE__->add_columns( data_type => 'datetime', is_nullable => 1, }, + 'twokeysfk' => { + data_type => 'integer', + is_nullable => 1, + }, ); __PACKAGE__->set_primary_key('id'); __PACKAGE__->belongs_to('owner', 'DBSchema::Result::User', { id => 'owner' }); __PACKAGE__->belongs_to('current_borrower', 'DBSchema::Result::User', { id => 'current_borrower' }); __PACKAGE__->has_many('dvdtags', 'Dvdtag', { 'foreign.dvd' => 'self.id' }); -__PACKAGE__->has_many('viewings', 'Viewing', { 'foreign.dvd_id' => 'self.id' }); +__PACKAGE__->has_many('viewings', 'DBSchema::Result::Viewing', { 'foreign.dvd_id' => 'self.id' }); __PACKAGE__->many_to_many('tags', 'dvdtags' => 'tag'); __PACKAGE__->might_have( liner_notes => 'DBSchema::Result::LinerNotes', undef, { proxy => [ qw/notes/ ] }, ); __PACKAGE__->add_relationship('like_has_many', 'DBSchema::Result::Twokeys', { 'foreign.dvd_name' => 'self.name' }, { accessor_name => 'like_has_many' } ); - +__PACKAGE__->add_relationship('like_has_many2', 'DBSchema::Result::Twokeys_belongsto', + { 'foreign.key1' => 'self.twokeysfk' }, +); 1; diff --git a/t/lib/DBSchema/Result/Onekey.pm b/t/lib/DBSchema/Result/Onekey.pm new file mode 100644 index 0000000..0797c04 --- /dev/null +++ b/t/lib/DBSchema/Result/Onekey.pm @@ -0,0 +1,24 @@ +package DBSchema::Result::Onekey; + +# Created by DBIx::Class::Schema::Loader v0.03000 @ 2006-10-02 08:24:09 + +use strict; +use warnings; + +use base 'DBIx::Class'; + +__PACKAGE__->load_components("PK::Auto", "Core"); +__PACKAGE__->table("onekey"); +__PACKAGE__->add_columns( + "id" => { data_type => 'integer', is_auto_increment => 1 }, + name => { data_type => 'varchar', size => 100, is_nullable => 1 }, +); +__PACKAGE__->set_primary_key("id"); + +__PACKAGE__->might_have( + twokeys_belongsto => 'DBSchema::Result::Twokeys_belongsto', 'key1', +); + + +1; + diff --git a/t/lib/DBSchema/Result/Twokeys_belongsto.pm b/t/lib/DBSchema/Result/Twokeys_belongsto.pm new file mode 100644 index 0000000..3f35aa0 --- /dev/null +++ b/t/lib/DBSchema/Result/Twokeys_belongsto.pm @@ -0,0 +1,24 @@ +package DBSchema::Result::Twokeys_belongsto; + +# Created by DBIx::Class::Schema::Loader v0.03000 @ 2006-10-02 08:24:09 + +use strict; +use warnings; + +use base 'DBIx::Class'; + +__PACKAGE__->load_components("PK::Auto", "Core"); +__PACKAGE__->table("twokeys_belongsto"); +__PACKAGE__->add_columns( + "key1" => { data_type => 'integer' }, + "key2" => { data_type => 'integer' }, +); +__PACKAGE__->set_primary_key("key1", "key2"); + +__PACKAGE__->add_relationship('like_belongs_to', 'DBSchema::Result::Dvd', { 'foreign.twokeysfk' => 'self.key1' }, ); + +__PACKAGE__->belongs_to('onekey', 'DBSchema::Result::Onekey', { 'foreign.id' => 'self.key1' }, ); + + +1; + diff --git a/t/lib/RunTests.pm b/t/lib/RunTests.pm index 0c877f8..e8c601d 100644 --- a/t/lib/RunTests.pm +++ b/t/lib/RunTests.pm @@ -9,7 +9,7 @@ use Test::More; sub run_tests{ my $schema = shift; - plan tests => 25; + plan tests => 27; my $dvd_rs = $schema->resultset( 'Dvd' ); my $user_rs = $schema->resultset( 'User' ); @@ -23,7 +23,6 @@ sub run_tests{ my $updates; $updates = { - id => undef, name => 'Test name 2', viewings => [ { user_id => $owner->id } ], owner => { id => $another_owner->id }, @@ -40,7 +39,6 @@ sub run_tests{ # creating new records my $updates = { - id => undef, aaaa => undef, tags => [ '2', { id => '3' } ], name => 'Test name', @@ -56,6 +54,12 @@ sub run_tests{ like_has_many => [ { key2 => 1 } ], + like_has_many2 => [ + { + onekey => { name => 'aaaaa' }, + key2 => 1 + } + ], }; my $dvd = $dvd_rs->recursive_update( $updates ); @@ -69,7 +73,12 @@ sub run_tests{ is ( $dvd->current_borrower->name, 'temp name', 'Related record created' ); is ( $dvd->liner_notes->notes, 'test note', 'might_have record created' ); ok ( $schema->resultset( 'Twokeys' )->find( { dvd_name => 'Test name', key2 => 1 } ), 'Twokeys created' ); - # changing existing records + my $onekey = $schema->resultset( 'Onekey' )->search( name => 'aaaaa' )->first; + ok ( $onekey, 'Onekey created' ); + ok ( $schema->resultset( 'Twokeys_belongsto' )->find( { key1 => $onekey->id, key2 => 1 } ), 'Twokeys created' ); + + +# changing existing records my $num_of_users = $user_rs->count; $updates = { @@ -86,6 +95,7 @@ sub run_tests{ liner_notes => { notes => 'test note changed', }, + }; $dvd = $dvd_rs->recursive_update( $updates ); @@ -100,18 +110,15 @@ sub run_tests{ # repeatable $updates = { - id => undef, name => 'temp name', username => 'temp username', password => 'temp username', owned_dvds =>[ { - 'id' => undef, 'name' => 'temp name 1', 'tags' => [ 1, 2 ], }, { - 'id' => undef, 'name' => 'temp name 2', 'tags' => [ 2, 3 ], } diff --git a/t/var/dvdzbr.db b/t/var/dvdzbr.db index 6e962cf..0388199 100644 Binary files a/t/var/dvdzbr.db and b/t/var/dvdzbr.db differ