From: Toby Corkindale Date: Mon, 20 Dec 2010 02:27:09 +0000 (+1100) Subject: Make sure indeterministic relationship data is ignored during 'find' of find_or_create X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fpeople%2Friba%2Ffind_or_create_buggery;p=dbsrgits%2FDBIx-Class.git Make sure indeterministic relationship data is ignored during 'find' of find_or_create --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index d826e03..db0a940 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -700,7 +700,12 @@ sub find { $relinfo->{cond}, $val, $key ); die "Can't handle complex relationship conditions in find" if ref($rel_q) ne 'HASH'; - @related{keys %$rel_q} = values %$rel_q; + + # an undef coming back from a cond resolution would imply + # no resolution is possible, hence ignore it altogether during + # the find (probably supplied as part of find_or_create) + @related{keys %$rel_q} = values %$rel_q + unless grep { ! defined } values %$rel_q; } } diff --git a/t/relationship/update_or_create_single.t b/t/relationship/update_or_create_single.t index a0e31fb..a1e8449 100644 --- a/t/relationship/update_or_create_single.t +++ b/t/relationship/update_or_create_single.t @@ -7,8 +7,6 @@ use DBICTest; my $schema = DBICTest->init_schema(); -plan tests => 9; - my $artist = $schema->resultset ('Artist')->first; my $genre = $schema->resultset ('Genre') @@ -95,3 +93,44 @@ is_deeply ( }, 'CD year column updated correctly without a disambiguator', ); + +# Test multi-level find-or-create functionality. +# We should be able to find-or-create this twice, with the second time +# returning the same item and genre as the first.. +my $genre_name = 'Highlander'; +my %cd_details = ( + year => '2010', + title => 'Tasty Treats', + genre => { name => $genre_name } +); +my $genre2 = $schema->resultset ('Genre') + ->create ({ name => $genre_name }); + +my $found1 = $artist->find_or_create_related('cds', { %cd_details }); +ok($found1->id, "Found (actually created) album in first iteration"); +is($found1->genre->name, $genre_name, ".. with correct genre"); + +my $found2 = $artist->find_or_create_related('cds', { %cd_details }); +ok($found2->id, "Found album in second iteration"); +is($found2->id, $found1->id, "..and the IDs are the same."); +is($found2->genre->name, $genre_name, ".. with correct genre"); + +# Now we repeat the tests, using a sub-level query on one of the critical +# keys that could be used in the "find" part. +my $artist_name = 'Peanut and Cashew Mix'; +my %new_cd = ( + year => '2011', + title => 'Various Failures', + artist => { name => $artist_name }, +); +my $found3 = $genre2->find_or_create_related('cds', { %new_cd }); +ok($found3->id, "Found (actually created) album in first iteration"); +is($found3->artist->name, $artist_name, "..with correct artist name"); + +my $found4 = $genre2->find_or_create_related('cds', { %new_cd }); +ok($found4->id, "Found album in second iteration"); +is($found4->id, $found3->id, "..and the IDs are the same."); +is($found4->artist->name, $artist_name, ".. with correct artist name"); +is($found4->artist->id, $found3->artist->id, "..matching artist ids"); + +done_testing;