add support for has_many relationships (RT#65168)
Alexander Hartmaier [Tue, 26 Nov 2019 15:39:02 +0000 (16:39 +0100)]
remove update_object_relation method
replaced by DBIx::Class::ResultSet::RecursiveUpdate

Changes
dist.ini
lib/Catalyst/Controller/DBIC/API.pm
t/lib/RestTest/Schema/Result/Track.pm

diff --git a/Changes b/Changes
index 8fa0ccf..24886df 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,9 @@
 Revision history for Catalyst-Controller-DBIC-API: {{ $dist->version }}
 
 {{ $NEXT }}
+  - Add support for has_many relationships (RT#65168)
+  - Remove update_object_relation method
+    replaced by DBIx::Class::ResultSet::RecursiveUpdate
 
 2.007002  2018-08-02 21:55:55+02:00 Europe/Vienna
   - Remove the debug logging which shouldn't have been in the previous release
index 25c2236..c954db7 100644 (file)
--- a/dist.ini
+++ b/dist.ini
@@ -42,6 +42,7 @@ repository.web = http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits/Catalys
 [Prereqs]
 perl = 5.008006
 DBIx::Class = 0.08103
+DBIx::Class::ResultSet::RecursiveUpdate = 0.40
 Catalyst::Runtime = 5.90020
 Catalyst::Action::Serialize = 0.83
 CGI::Expand = 2.02
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);
+        }
     }
 }
 
index eb1382a..480e293 100644 (file)
@@ -15,8 +15,7 @@ __PACKAGE__->add_columns(
   },
   'position' => {
     data_type => 'integer',
-    accessor => 'pos',
-               default_value => 0
+    default_value => 0
   },
   'title' => {
     data_type => 'varchar',