On Jan 5, 2008 7:05 PM, Jess Robinson <[EMAIL PROTECTED]> wrote:
>
>
> On Sat, 5 Jan 2008, Zbigniew Lukasiak wrote:
>
> > Happy New Year!
> >
> > I've recently learned that in DBIC you can do something like:
> >
> > $user_rs->create( { name => 'new nick', addresses => [
> >            { address => 'new address' },
> >            { address => 'new address 2' },
> >            ]
> >      }
> > );
>
> Funky ain't it, I did that ;)
>
> > When refactoring the FormFu::Model::DBIC code I've reached a point
> > where it would be useful to do:
> > $user->update_with_relations( { name => 'new nick', addresses => [
> >            { id => 2, address => 'new home' },
> >            { id => 3, address => 'new office'},
> >            { id => undef, address => 'new address'},
> >            ]
> >        }
> >    );
> > and have the (already existing) related rows updated.  Unfortunately
> > when I do that DBIC tries to insert them and fails because their ids
> > are already taken (the last one, with id => undef, works as expected -
> > a new row is inserted).
>
> Not yet, but it's a logical follow on, may be somewhat more interesting to
> do though.. OTOH nothingmuch has just helped by factoring out a part of
> the code.
>
> new() currently does a find_or_new on all the related bits, then insert()
> inserts them if needed.
>
> update() should likely do similar, plus inserting if new relateds are
> added. I'm surprised the undef got inserted..

OK - so the updating can be done relatively simply - by just changing
create_related to update_or_create_related in set_inflated_columns in
DBIx::Class::Row. The problem is with unrelating the rows that are not
included in the list.  Should they be deleted or just the foreign key
should be set to null?

I attach the svn diff (together with test cases).

This was the has_many case - the many_to_many should actually be
simpler - this will be my next task.

cheers,
Zbigniew
http://perlalchemy.blogspot.com
Index: t/69update.t
===================================================================
--- t/69update.t	(revision 3934)
+++ t/69update.t	(working copy)
@@ -9,7 +9,7 @@
 
 BEGIN {
         eval "use DBD::SQLite";
-        plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 6);
+        plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 8);
 }                                                                               
 
 my $art = $schema->resultset("Artist")->find(1);
@@ -34,3 +34,32 @@
 my $art_100 = $schema->resultset("Artist")->find(100);
 $art_100->artistid(101);
 ok($art_100->update(), 'update allows pk mutation via column accessor');
+
+$art_100->cds->delete;
+$art_100->update( { 
+        cds => [ 
+        { title => 'Picnic at Hanging Rock', year => '1975' }, 
+        { title => 'Blade Runner', year => '1982' },
+        { title => 'The Deer Hunter', year => '1978' }
+        ] 
+    } 
+);
+my @cds = $art_100->cds;
+my $picnick_id = $art_100->cds->search( { title => 'Picnic at Hanging Rock' } )->first->cdid;
+my $bladerunner_id = $art_100->cds->search( { title => 'Blade Runner' } )->first->cdid;
+is ( scalar @cds, 3, 'CDs create in an update' );
+
+$art_100->update( { 
+        cds => [ 
+        { cdid => $picnick_id, title => 'Picnic at Hanging Rock', year => '1975' }, 
+        { cdid => $bladerunner_id, title => 'Blade Runner', year => '2007' }
+        ] 
+    } 
+);
+# What to do with the 'The Deer Hunter' - which should now be unrelated? 
+# Should it be deleted or just the foreign key should be set to NULL?
[EMAIL PROTECTED] = $art_100->cds;
+#is ( scalar @cds, 2, 'CDs number correct after artist update' );
+my $bladerunner = $schema->resultset("CD")->find($bladerunner_id);
+is ( $bladerunner->year, '2007', 'CD updated in an artist update' );
+
Index: lib/DBIx/Class/Row.pm
===================================================================
--- lib/DBIx/Class/Row.pm	(revision 3934)
+++ lib/DBIx/Class/Row.pm	(working copy)
@@ -507,7 +507,7 @@
         my $others = delete $upd->{$key};
         foreach my $rel_obj (@$others) {
           if(!Scalar::Util::blessed($rel_obj)) {
-            $rel_obj = $self->create_related($key, $rel_obj);
+            $rel_obj = $self->update_or_create_related($key, $rel_obj);
           }
         }
         $self->{_relationship_data}{$key} = $others; 
_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[EMAIL PROTECTED]

Reply via email to