Add missing deprecation warnings on m2m set_*, tighten up code
Peter Rabbitson [Thu, 13 Aug 2015 09:40:55 +0000 (11:40 +0200)]
Back in the day 4d3a827d had the right idea but did not implement actual
deprecation carp()s. Then ac36a402 added support for a link-data arg, making
things even murkier... sigh.

Changes
lib/DBIx/Class/Relationship/ManyToMany.pm
t/relationship/core.t
t/relationship/custom.t

diff --git a/Changes b/Changes
index 79647e8..e4b1733 100644 (file)
--- a/Changes
+++ b/Changes
@@ -5,6 +5,8 @@ Revision history for DBIx::Class
           an underlying search_rs(), as by design these arguments would be
           used only on the first call to ->related_resultset(), and ignored
           afterwards. Instead an exception (detailing the fix) is thrown.
+        - Calling the set_* many-to-many helper with a list (instead of an
+          arrayref) now emits a deprecation warning
 
     * New Features
         - DBIx::Class::Optional::Dependencies now properly understands
index 6dfa22e..c5f4570 100644 (file)
@@ -108,9 +108,28 @@ EOW
 
     my $set_meth_name = join '::', $class, $set_meth;
     *$set_meth_name = subname $set_meth_name, sub {
+
       my $self = shift;
-      @_ > 0 or $self->throw_exception(
-        "{$set_meth} needs a list of objects or hashrefs"
+
+      my $set_to = ( ref $_[0] eq 'ARRAY' )
+        ? ( shift @_ )
+        : do {
+          carp_unique(
+            "Calling '$set_meth' with a list of items to link to is deprecated, use an arrayref instead"
+          );
+
+          # gobble up everything from @_ into a new arrayref
+          [ splice @_ ]
+        }
+      ;
+
+      # make sure folks are not invoking a bizarre mix of deprecated and curent syntax
+      $self->throw_exception(
+        "'$set_meth' expects an arrayref of objects or hashrefs to link to, and an optional hashref of link data"
+      ) if (
+        @_ > 1
+          or
+        ( @_ and ref $_[0] ne 'HASH' )
       );
 
       my $guard = $self->result_source->schema->storage->txn_scope_guard;
@@ -124,8 +143,10 @@ EOW
         $self->search_related( $rel, {} )->delete;
       }
       # add in the set rel objects
-      $self->$add_meth($_, ref($_[1]) ? $_[1] : {})
-        for ( ref($_[0]) eq 'ARRAY' ? @{ $_[0] } : @_ );
+      $self->$add_meth(
+        $_,
+        @_, # at this point @_ is either empty or contains a lone link-data hash
+      ) for @$set_to;
 
       $guard->commit;
     };
index e0e243c..21ce508 100644 (file)
@@ -3,6 +3,7 @@ use warnings;
 
 use Test::More;
 use Test::Exception;
+use Test::Warn;
 use lib qw(t/lib);
 use DBICTest ':DiffSQL';
 
@@ -190,11 +191,18 @@ is( $prod_rs->first->name, 'Testy McProducer',
     'many_to_many add_to_$rel($hash) ok' );
 $cd->add_to_producers({ name => 'Jack Black' });
 is( $prod_rs->count(), 2, 'many_to_many add_to_$rel($hash) count ok' );
-$cd->set_producers($schema->resultset('Producer')->all);
-is( $cd->producers->count(), $prod_before_count+2,
-    'many_to_many set_$rel(@objs) count ok' );
-$cd->set_producers($schema->resultset('Producer')->find(1));
-is( $cd->producers->count(), 1, 'many_to_many set_$rel($obj) count ok' );
+
+warnings_like {
+  $cd->set_producers($schema->resultset('Producer')->all);
+  is( $cd->producers->count(), $prod_before_count+2,
+      'many_to_many set_$rel(@objs) count ok' );
+
+  $cd->set_producers($schema->resultset('Producer')->find(1));
+  is( $cd->producers->count(), 1, 'many_to_many set_$rel($obj) count ok' );
+} [
+  ( qr/\QCalling 'set_producers' with a list of items to link to is deprecated, use an arrayref instead/ ) x 2
+], 'Warnings on deprecated invocation of set_* found';
+
 $cd->set_producers([$schema->resultset('Producer')->all]);
 is( $cd->producers->count(), $prod_before_count+2,
     'many_to_many set_$rel(\@objs) count ok' );
index 058636b..b9bf5fa 100644 (file)
@@ -301,7 +301,7 @@ for (qw( artist_limited_rank artist_limited_rank_opaque )) {
   );
 
   # can't use the opaque one - need set_from_related to work
-  $artwork->set_artist_limited_rank( @artists );
+  $artwork->set_artist_limited_rank( \@artists );
 
   {
     local $TODO = 'Taking into account the relationship bridge condition is not likely to ever work... unless we get DQ hooked somehow';