X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRelationship%2FBase.pm;h=286825095e54f8adb0b436d030f878a3e60f6032;hb=ee333775;hp=a41d6b4df0b1d15874a6df2da4f58f93f087e2de;hpb=a5fc497548f9f980d3fd1deb7b7cb9095d079651;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Relationship/Base.pm b/lib/DBIx/Class/Relationship/Base.pm index a41d6b4..2868250 100644 --- a/lib/DBIx/Class/Relationship/Base.pm +++ b/lib/DBIx/Class/Relationship/Base.pm @@ -7,6 +7,7 @@ use base qw/DBIx::Class/; use Scalar::Util qw/weaken blessed/; use Try::Tiny; +use DBIx::Class::_Util 'UNRESOLVABLE_CONDITION'; use namespace::clean; =head1 NAME @@ -38,11 +39,11 @@ methods, for predefined ones, look in L. =over 4 -=item Arguments: 'relname', 'Foreign::Class', $condition, $attrs +=item Arguments: $rel_name, $foreign_class, $condition, $attrs =back - __PACKAGE__->add_relationship('relname', + __PACKAGE__->add_relationship('rel_name', 'Foreign::Class', $condition, $attrs); @@ -183,7 +184,7 @@ While every coderef-based condition must return a valid C clause, it may elect to additionally return a simplified join-free condition hashref when invoked as C<< $result->relationship >>, as opposed to C<< $rs->related_resultset('relationship') >>. In this case C<$result> is -passed to the coderef as C<< $args->{self_rowobj} >>, so a user can do the +passed to the coderef as C<< $args->{self_resultobj} >>, so a user can do the following: sub { @@ -194,8 +195,8 @@ following: "$args->{foreign_alias}.artist" => { -ident => "$args->{self_alias}.artistid" }, "$args->{foreign_alias}.year" => { '>', "1979", '<', "1990" }, }, - $args->{self_rowobj} && { - "$args->{foreign_alias}.artist" => $args->{self_rowobj}->artistid, + $args->{self_resultobj} && { + "$args->{foreign_alias}.artist" => $args->{self_resultobj}->artistid, "$args->{foreign_alias}.year" => { '>', "1979", '<', "1990" }, }, ); @@ -232,11 +233,20 @@ clause, the C<$args> hashref passed to the subroutine contains some extra metadata. Currently the supplied coderef is executed as: $relationship_info->{cond}->({ - self_alias => The alias of the invoking resultset ('me' in case of a result object), - foreign_alias => The alias of the to-be-joined resultset (often matches relname), - self_resultsource => The invocant's resultsource, - foreign_relname => The relationship name (does *not* always match foreign_alias), - self_rowobj => The invocant itself in case of a $result_object->$relationship call + self_resultsource => The resultsource instance on which rel_name is registered + rel_name => The relationship name (does *NOT* always match foreign_alias) + + self_alias => The alias of the invoking resultset + foreign_alias => The alias of the to-be-joined resultset (does *NOT* always match rel_name) + + # only one of these (or none at all) will ever be supplied to aid in the + # construction of a join-free condition + self_resultobj => The invocant object itself in case of a $resultobj->$rel_name() call + foreign_resultobj => The related object in case of $resultobj->set_from_related($rel_name, $foreign_resultobj) + + # deprecated inconsistent names, will be forever available for legacy code + self_rowobj => Old deprecated slot for self_resultobj + foreign_relname => Old deprecated slot for rel_name }); =head3 attributes @@ -483,18 +493,12 @@ sub related_resultset { $rsrc->_resolve_condition( $rel_info->{cond}, $rel, $self, $rel ) } catch { - if ($self->in_storage) { - $self->throw_exception ($_); - } - - $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION; # RV + $self->throw_exception ($_) if $self->in_storage; + UNRESOLVABLE_CONDITION; # RV, no return() }; # keep in mind that the following if() block is part of a do{} - no return()s!!! - if ($is_crosstable) { - $self->throw_exception ( - "A cross-table relationship condition returned for statically declared '$rel'" - ) unless ref $rel_info->{cond} eq 'CODE'; + if ($is_crosstable and ref $rel_info->{cond} eq 'CODE') { # A WHOREIFFIC hack to reinvoke the entire condition resolution # with the correct alias. Another way of doing this involves a @@ -519,7 +523,7 @@ sub related_resultset { # FIXME - this conditional doesn't seem correct - got to figure out # at some point what it does. Also the entire UNRESOLVABLE_CONDITION # business seems shady - we could simply not query *at all* - if ($cond eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION) { + if ($cond eq UNRESOLVABLE_CONDITION) { my $reverse = $rsrc->reverse_relationship_info($rel); foreach my $rev_rel (keys %$reverse) { if ($reverse->{$rev_rel}{attrs}{accessor} && $reverse->{$rev_rel}{attrs}{accessor} eq 'multi') { @@ -637,26 +641,27 @@ sub new_related { # sanity check - currently throw when a complex coderef rel is encountered # FIXME - should THROW MOAR! - if (ref $self) { # cdbi calls this as a class method, /me vomits - my $rsrc = $self->result_source; my $rel_info = $rsrc->relationship_info($rel) or $self->throw_exception( "No such relationship '$rel'" ); - my (undef, $crosstable, $cond_targets) = $rsrc->_resolve_condition ( + my (undef, $crosstable, $nonequality_foreign_columns) = $rsrc->_resolve_condition ( $rel_info->{cond}, $rel, $self, $rel ); - $self->throw_exception("Custom relationship '$rel' does not resolve to a join-free condition fragment") + $self->throw_exception("Relationship '$rel' does not resolve to a join-free condition fragment") if $crosstable; - if (my @unspecified_rel_condition_chunks = grep { ! exists $values->{$_} } @{$cond_targets||[]} ) { + if ( + $nonequality_foreign_columns + and + my @unspecified_rel_condition_chunks = grep { ! exists $values->{$_} } @$nonequality_foreign_columns + ) { $self->throw_exception(sprintf ( "Custom relationship '%s' not definitive - returns conditions instead of values for column(s): %s", $rel, map { "'$_'" } @unspecified_rel_condition_chunks )); } - } return $self->search_related($rel)->new_result($values); } @@ -818,16 +823,17 @@ sub set_from_related { # # sanity check - currently throw when a complex coderef rel is encountered # FIXME - should THROW MOAR! - my ($cond, $crosstable, $cond_targets) = $rsrc->_resolve_condition ( + my ($cond, $crosstable, $nonequality_foreign_columns) = $rsrc->_resolve_condition ( $rel_info->{cond}, $f_obj, $rel, $rel ); - $self->throw_exception("Custom relationship '$rel' does not resolve to a join-free condition fragment") + $self->throw_exception("Relationship '$rel' does not resolve to a join-free condition fragment") if $crosstable; + $self->throw_exception(sprintf ( "Custom relationship '%s' not definitive - returns conditions instead of values for column(s): %s", $rel, - map { "'$_'" } @$cond_targets - )) if $cond_targets; + map { "'$_'" } @$nonequality_foreign_columns + )) if $nonequality_foreign_columns; $self->set_columns($cond);