preparing docs for release
John Napiorkowski [Wed, 25 Mar 2015 16:39:13 +0000 (11:39 -0500)]
Changes
lib/Catalyst.pm
lib/Catalyst/DispatchType/Chained.pm
lib/Catalyst/Runtime.pm
lib/Catalyst/Upgrading.pod
t/args0_bug.t

diff --git a/Changes b/Changes
index db97404..b5d1403 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,15 @@
 # This file documents the revision history for Perl extension Catalyst.
 
+5.90085 - 2014-03-25
+  - Small change to Catalyst::Action to prevent autovivication of Args value (dim1++)
+  - Minor typo fixes (Abraxxa++)
+  - Make sure than when using chained actions and when more than one action
+    matches the same path specification AND has Args(0), that we follow the
+    "in a tie, the last action defined wins" rule.  There is a small chance
+    this is a breaking change for you.  See Catalyst::Upgrading for more.
+    You may use the application configuration setting "use_chained_args_0_special_case"
+    to disable this new behavior, if you must.
+
 5.90084 - 2015-02-23
   - Small change to the way body parameters are created in order to prevent
     trying to create parameters twice.
index 92621a1..4d28b83 100644 (file)
@@ -129,7 +129,7 @@ __PACKAGE__->stats_class('Catalyst::Stats');
 __PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
 
 # Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90084';
+our $VERSION = '5.90085';
 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
 
 sub import {
@@ -3904,6 +3904,18 @@ parameter to true.
 
 =item *
 
+C<use_chained_args_0_special_case>
+
+In older versions of Catalyst, when more than one action matched the same path
+AND all those matching actions declared Args(0), we'd break the tie by choosing
+the first action defined.  We now normalized how Args(0) works so that it
+follows the same rule as Args(N), which is to say when we need to break a tie
+we choose the LAST action defined.  If this breaks your code and you don't
+have time to update to follow the new normalized approach, you may set this
+value to true and it will globally revert to the original chaining behavior.
+
+=item *
+
 C<psgi_middleware> - See L<PSGI MIDDLEWARE>.
 
 =item *
index b733242..831f6e8 100644 (file)
@@ -294,7 +294,13 @@ sub recurse_match {
                         defined($args_attr) && 
                         (
                             $args_attr eq "0" &&
-                            ( exists($best_action->{args_attr}) && defined($best_action->{args_attr}) ?  ($best_action->{args_attr} ne 0) : 1 )
+                            (
+                              ($c->config->{use_chained_args_0_special_case}||0) || 
+                                (
+                                  exists($best_action->{args_attr}) && defined($best_action->{args_attr}) ?
+                                  ($best_action->{args_attr} ne 0) : 1
+                                )
+                            )
                         )
                     )
                 ){
index 09b70c9..4e16a4f 100644 (file)
@@ -7,7 +7,7 @@ BEGIN { require 5.008003; }
 
 # Remember to update this in Catalyst as well!
 
-our $VERSION = '5.90084';
+our $VERSION = '5.90085';
 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
 
 =head1 NAME
index ebfa2a3..79a90ec 100644 (file)
@@ -2,6 +2,70 @@
 
 Catalyst::Upgrading - Instructions for upgrading to the latest Catalyst
 
+=head1 Upgrading to Catalyst 5.90085
+
+In this version of Catalyst we made a small change to Chained Dispatching so
+that when two or more actions all have the same path specification AND they
+all have Args(0), we break the tie by choosing the last action defined, and
+not the first one defined.  This was done to normalize Chaining to following
+the 'longest Path wins, and when several actions match the same Path specification
+we choose the last defined.' rule. Previously Args(0) was hard coded to be a special
+case such that the first action defined would match (which is not the case when
+Args is not zero.)
+
+Its possible that this could be a breaking change for you, if you had used
+action roles (custom or otherwise) to add additional matching rules to differentiate
+between several Args(0) actions that share the same root action chain.  For
+example if you have code now like this:
+
+    sub check_default :Chained(/) CaptureArgs(0) { ... }
+
+      sub default_get :Chained('check_default') PathPart('') Args(0) GET {
+          pop->res->body('get3');
+      }
+
+      sub default_post :Chained('check_default') PathPart('') Args(0) POST {
+          pop->res->body('post3');
+      }
+
+      sub chain_default :Chained('check_default') PathPart('') Args(0) {
+          pop->res->body('chain_default');
+      }
+
+The way that chaining will work previous is that when two or more equal actions can
+match, the 'top' one wins.  So if the request is "GET .../check_default" BOTH
+actions 'default_get' AND 'chain_default' would match.  To break the tie in
+the case when Args is 0, we'd previous take the 'top' (or first defined) action.
+Unfortunately this treatment of Args(0) is special case.  In all other cases
+we choose the 'last defined' action to break a tie.  So this version of
+Catalyst changed the dispatcher to make Args(0) no longer a special case for
+breaking ties.  This means that the above code must now become:
+
+    sub check_default :Chained(/) CaptureArgs(0) { ... }
+
+      sub chain_default :Chained('check_default') PathPart('') Args(0) {
+          pop->res->body('chain_default');
+      }
+
+      sub default_get :Chained('check_default') PathPart('') Args(0) GET {
+          pop->res->body('get3');
+      }
+
+      sub default_post :Chained('check_default') PathPart('') Args(0) POST {
+          pop->res->body('post3');
+      }
+
+If we want it to work as expected (for example we we GET to match 'default_get' and
+POST to match 'default_post' and any other http Method to match 'chain_default').
+
+In other words Arg(0) and chained actions must now follow the normal rule where
+in a tie the last defined action wins and you should place all your less defined
+or 'catch all' actions first.
+
+If this causes you trouble and you can't fix your code to conform, you may set the
+application configuration setting "use_chained_args_0_special_case" to true and
+that will revert you code to the previous behavior.
+
 =head1 Upgrading to Catalyst 5.90080
 
 UTF8 encoding is now default.  For temporary backwards compatibility, if this
index 4f6fd48..71f2512 100644 (file)
@@ -24,6 +24,7 @@ use Test::More;
   package MyApp;
   use Catalyst;
 
+  #MyApp->config(use_chained_args_0_special_case=>1);
   MyApp->setup;
 }