add support for has_many relationships (RT#65168)
[catagits/Catalyst-Controller-DBIC-API.git] / lib / Catalyst / Controller / DBIC / API.pm
index fc929cb..6638e9b 100644 (file)
@@ -13,6 +13,7 @@ use Moose::Util;
 use Scalar::Util( 'blessed', 'reftype' );
 use Try::Tiny;
 use Catalyst::Controller::DBIC::API::Request;
+use DBIx::Class::ResultSet::RecursiveUpdate;
 use namespace::autoclean;
 
 has '_json' => (
@@ -694,14 +695,32 @@ sub validate_object {
                 ? [ $related_source->columns ]
                 : $allowed_fields;
 
-            foreach my $related_col ( @{$allowed_related_cols} ) {
-                if (defined(
-                        my $related_col_value =
-                            $related_params->{$related_col}
-                    )
-                    )
-                {
-                    $values{$key}{$related_col} = $related_col_value;
+            if (ref($related_params) && reftype($related_params) eq 'ARRAY') {
+                my @related_data;
+                for my $related_param (@$related_params) {
+                    my %data;
+                    foreach my $related_col ( @{$allowed_related_cols} ) {
+                        if (defined(
+                                my $related_col_value =
+                                    $related_param->{$related_col}
+                            )
+                        ) {
+                            $data{$related_col} = $related_col_value;
+                        }
+                    }
+                    push @related_data, \%data;
+                }
+                $values{$key} = \@related_data;
+            }
+            else {
+                foreach my $related_col ( @{$allowed_related_cols} ) {
+                    if (defined(
+                            my $related_col_value =
+                                $related_params->{$related_col}
+                        )
+                    ) {
+                        $values{$key}{$related_col} = $related_col_value;
+                    }
                 }
             }
         }
@@ -813,66 +832,19 @@ object, and the relation parameters. Then it calls ->update on the object.
 sub update_object_from_params {
     my ( $self, $c, $object, $params ) = @_;
 
-    foreach my $key ( keys %$params ) {
-        my $value = $params->{$key};
-        if ( ref($value) && !( reftype($value) eq reftype(JSON::MaybeXS::true) ) ) {
-            $self->update_object_relation( $c, $object,
-                delete $params->{$key}, $key );
-        }
-
-        # accessor = colname
-        elsif ( $object->can($key) ) {
-            $object->$key($value);
-        }
-
-        # accessor != colname
-        else {
-            my $accessor =
-                $object->result_source->column_info($key)->{accessor};
-            $object->$accessor($value);
-        }
-    }
-
-    $object->update();
-}
+    $params = {%$params, %{$object->ident_condition}};
 
-=method_protected update_object_relation
-
-update_object_relation finds the relation to the object, then calls ->update
-with the specified parameters.
-
-=cut
-
-sub update_object_relation {
-    my ( $self, $c, $object, $related_params, $relation ) = @_;
-    my $row = $object->find_related( $relation, {}, {} );
-
-    if ($row) {
-        foreach my $key ( keys %$related_params ) {
-            my $value = $related_params->{$key};
-            if ( ref($value) && !( reftype($value) eq reftype(JSON::MaybeXS::true) ) )
-            {
-                $self->update_object_relation( $c, $row,
-                    delete $related_params->{$key}, $key );
-            }
-
-            # accessor = colname
-            elsif ( $row->can($key) ) {
-                $row->$key($value);
-            }
+    my $updated_object =
+        DBIx::Class::ResultSet::RecursiveUpdate::Functions::recursive_update(
+        resultset => $c->req->current_result_set,
+        # unknown_params_ok => 1,
+        updates => $params,
+    );
 
-            # accessor != colname
-            else {
-                my $accessor =
-                    $row->result_source->column_info($key)->{accessor};
-                $row->$accessor($value);
-            }
-        }
-        $row->update();
-    }
-    else {
-        $object->create_related( $relation, $related_params );
-    }
+    # replace request object with updated one for response
+    my $vals = $c->req->get_object(0)->[1];
+    $c->req->clear_objects;
+    $c->req->add_object( [ $updated_object, $vals ] );
 }
 
 =method_protected insert_object_from_params
@@ -908,7 +880,14 @@ sub insert_object_from_params {
     $object->insert;
 
     while ( my ( $k, $v ) = each %rels ) {
-        $object->create_related( $k, $v );
+        if (reftype($v) eq 'ARRAY') {
+            foreach my $next_v ( @$v ) {
+                $object->create_related($k, $next_v);
+            }
+        }
+        else {
+            $object->create_related($k => $v);
+        }
     }
 }