Another heavy refactor of the rel resolver prototype (sequel to 03f6d1f7)
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Relationship / Base.pm
index e11263f..e0007ff 100644 (file)
@@ -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
@@ -183,7 +184,7 @@ While every coderef-based condition must return a valid C<ON> 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" },
       },
     );
@@ -493,7 +494,7 @@ sub related_resultset {
     }
     catch {
       $self->throw_exception ($_) if $self->in_storage;
-      $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION;  # RV, no return()
+      UNRESOLVABLE_CONDITION;  # RV, no return()
     };
 
     # keep in mind that the following if() block is part of a do{} - no return()s!!!
@@ -522,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') {
@@ -630,42 +631,15 @@ your storage until you call L<DBIx::Class::Row/insert> on it.
 =cut
 
 sub new_related {
-  my ($self, $rel, $values) = @_;
-
-  # FIXME - this is a bad position for this (also an identical copy in
-  # set_from_related), but I have no saner way to hook, and I absolutely
-  # want this to throw at least for coderefs, instead of the "insert a NULL
-  # when it gets hard" insanity --ribasushi
-  #
-  # 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, $nonequality_foreign_columns) = $rsrc->_resolve_condition (
-      $rel_info->{cond}, $rel, $self, $rel
-    );
-
-    $self->throw_exception("Relationship '$rel' does not resolve to a join-free condition fragment")
-      if $crosstable;
-
-    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);
+  my ($self, $rel, $data) = @_;
+
+  return $self->search_related($rel)->new_result( $self->result_source->_resolve_relationship_condition (
+    infer_values_based_on => $data,
+    rel_name => $rel,
+    self_resultobj => $self,
+    foreign_alias => $rel,
+    self_alias => 'me',
+  )->{inferred_values} );
 }
 
 =head2 create_related
@@ -807,37 +781,13 @@ set them in the storage.
 sub set_from_related {
   my ($self, $rel, $f_obj) = @_;
 
-  my $rsrc = $self->result_source;
-  my $rel_info = $rsrc->relationship_info($rel)
-    or $self->throw_exception( "No such relationship '$rel'" );
-
-  if (defined $f_obj) {
-    my $f_class = $rel_info->{class};
-    $self->throw_exception( "Object '$f_obj' isn't a ".$f_class )
-      unless blessed $f_obj and $f_obj->isa($f_class);
-  }
-
-
-  # FIXME - this is a bad position for this (also an identical copy in
-  # new_related), but I have no saner way to hook, and I absolutely
-  # want this to throw at least for coderefs, instead of the "insert a NULL
-  # when it gets hard" insanity --ribasushi
-  #
-  # sanity check - currently throw when a complex coderef rel is encountered
-  # FIXME - should THROW MOAR!
-  my ($cond, $crosstable, $nonequality_foreign_columns) = $rsrc->_resolve_condition (
-    $rel_info->{cond}, $f_obj, $rel, $rel
-  );
-  $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 { "'$_'" } @$nonequality_foreign_columns
-  )) if $nonequality_foreign_columns;
-
-  $self->set_columns($cond);
+  $self->set_columns( $self->result_source->_resolve_relationship_condition (
+    infer_values_based_on => {},
+    rel_name => $rel,
+    foreign_resultobj => $f_obj,
+    foreign_alias => $rel,
+    self_alias => 'me',
+  )->{inferred_values} );
 
   return 1;
 }