X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRelationship%2FBase.pm;h=c4d111186007278bfaa1cde4acc705f8320d9042;hb=8848b5bd9ece2c0320b99ce616bd6f3ecd205159;hp=e2efc9987253bc4e9831ecb4a10de13f8c29994f;hpb=ef0845bad4b2945f8d5bb4157ba3aa9fe95ef790;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Relationship/Base.pm b/lib/DBIx/Class/Relationship/Base.pm index e2efc99..c4d1111 100644 --- a/lib/DBIx/Class/Relationship/Base.pm +++ b/lib/DBIx/Class/Relationship/Base.pm @@ -182,13 +182,31 @@ clause of the C statement associated with this relationship. While every coderef-based condition must return a valid C clause, it may elect to additionally return a simplified B 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_result_object} >>. Alternatively -the user-space could be calling C<< $result->set_from_related( $rel => -$foreign_related_object ) >>, in which case C<$foreign_related_object> will -be passed to the coderef as C<< $args->{foreign_result_object >>. In other -words if you define your condition coderef as: +consisting of a hashref with B. This boils down to two scenarios: + +=over + +=item * + +When relationship resolution is invoked after C<< $result->$rel_name >>, as +opposed to C<< $rs->related_resultset($rel_name) >>, the C<$result> object +is passed to the coderef as C<< $args->{self_result_object} >>. + +=item * + +Alternatively when the user-space invokes resolution via +C<< $result->set_from_related( $rel_name => $foreign_values_or_object ) >>, the +corresponding data is passed to the coderef as C<< $args->{foreign_values} >>, +B in the form of a hashref. If a foreign result object is supplied +(which is valid usage of L), its values will be extracted +into hashref form by calling L. + +=back + +Note that the above scenarios are mutually exclusive, that is you will be supplied +none or only one of C and C. In other words if +you define your condition coderef as: sub { my $args = shift; @@ -202,8 +220,8 @@ words if you define your condition coderef as: "$args->{foreign_alias}.artist" => $args->{self_result_object}->artistid, "$args->{foreign_alias}.year" => { '>', "1979", '<', "1990" }, }, - ! $args->{foreign_result_object} ? () : { - "$args->{self_alias}.artistid" => $args->{foreign_result_object}->artist, + ! $args->{foreign_values} ? () : { + "$args->{self_alias}.artistid" => $args->{foreign_values}{artist}, } ); } @@ -233,34 +251,38 @@ While this code: Will properly set the C<< $artist->artistid >> field of this new object to C<1> -Note that in order to be able to use -L<< $result->create_related|DBIx::Class::Relationship::Base/create_related >>, -the coderef must not only return as its second such a "simple" condition -hashref which does not depend on joins being available, but the hashref must -contain only plain values/deflatable objects, such that the result can be -passed directly to L. For -instance the C constraint in the above example prevents the relationship -from being used to create related objects (an exception will be thrown). +Note that in order to be able to use L (and by extension +L<< $result->create_related|DBIx::Class::Relationship::Base/create_related >>), +the returned join free condition B contain only plain values/deflatable +objects. For instance the C constraint in the above example prevents +the relationship from being used to create related objects using +C<< $artst->create_related( cds_80s => { title => 'blah' } ) >> (an +exception will be thrown). In order to allow the user to go truly crazy when generating a custom C clause, the C<$args> hashref passed to the subroutine contains some extra metadata. Currently the supplied coderef is executed as: $relationship_info->{cond}->({ - self_resultsource => The resultsource instance on which rel_name is registered - rel_name => The relationship name (does *NOT* always match foreign_alias) + 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) + 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_result_object => The invocant object itself in case of a $result_object->$rel_name( ... ) call - foreign_result_object => The related object in case of $result_object->set_from_related( $rel_name, $foreign_result_object ) + + self_result_object => The invocant *object* itself in case of a call like + $result_object->$rel_name( ... ) + + foreign_values => A *hashref* of related data: may be passed in directly or + derived via ->get_columns() from a related object in case of + $result_object->set_from_related( $rel_name, $foreign_result_object ) # deprecated inconsistent names, will be forever available for legacy code - self_rowobj => Old deprecated slot for self_result_object - foreign_relname => Old deprecated slot for rel_name + self_rowobj => Old deprecated slot for self_result_object + foreign_relname => Old deprecated slot for rel_name }); =head3 attributes @@ -384,7 +406,7 @@ the relationship attributes. The C relationship does not update across relationships by default, so if you have a 'proxy' attribute on a belongs_to and want to -use 'update' on it, you muse set C<< cascade_update => 1 >>. +use 'update' on it, you must set C<< cascade_update => 1 >>. This is not a RDMS style cascade update - it purely means that when an object has update called on it, all the related objects also @@ -798,7 +820,7 @@ sub set_from_related { $self->set_columns( $self->result_source->_resolve_relationship_condition ( infer_values_based_on => {}, rel_name => $rel, - foreign_result_object => $f_obj, + foreign_values => $f_obj, foreign_alias => $rel, self_alias => 'me', )->{inferred_values} );