Catalyst-Runtime
view release on metacpan or search on metacpan
lib/Catalyst/RouteMatching.pod view on Meta::CPAN
sub an_any :Path(user) Args(1) {
}
In this case L<Catalyst> will check actions starting from the LAST one defined. Generally
this means you should put your most specific action rules LAST and your 'catch-alls' first.
In the above example, since Args(1) will match any argument, you will find that that 'an_int'
action NEVER gets hit. You would need to reverse the order:
sub an_any :Path(user) Args(1) {
}
sub an_int :Path(user) Args(Int) {
}
Now requests that match this path would first hit the 'an_int' action and will check to see if
the argument is an integer. If it is, then the action will execute, otherwise it will pass and
the dispatcher will check the next matching action (in this case we fall through to the 'an_any'
action).
=head3 Type Constraints and Chained Actions
Using type constraints in Chained actions works the same as it does for Path and Local or Global
actions. The only difference is that you may declare type constraints on CaptureArgs as
well as Args. For Example:
use Types::Standard qw/Int Tuple/;
sub chain_base :Chained(/) CaptureArgs(1) { }
sub any_priority_chain :GET Chained(chain_base) PathPart('') Args(1) { }
sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
sub link_any :Chained(chain_base) PathPart('') CaptureArgs(1) { }
sub any_priority_link_any :Chained(link_any) PathPart('') Args(1) { }
sub int_priority_link_any :Chained(link_any) PathPart('') Args(Int) { }
sub link_int :Chained(chain_base) PathPart('') CaptureArgs(Int) { }
sub any_priority_link :Chained(link_int) PathPart('') Args(1) { }
sub int_priority_link :Chained(link_int) PathPart('') Args(Int) { }
sub link_int_int :Chained(chain_base) PathPart('') CaptureArgs(Int,Int) { }
sub any_priority_link2 :Chained(link_int_int) PathPart('') Args(1) { }
sub int_priority_link2 :Chained(link_int_int) PathPart('') Args(Int) { }
sub link_tuple :Chained(chain_base) PathPart('') CaptureArgs(Tuple[Int,Int,Int]) { }
sub any_priority_link3 :Chained(link_tuple) PathPart('') Args(1) { }
sub int_priority_link3 :Chained(link_tuple) PathPart('') Args(Int) { }
These chained actions might create match tables like the following:
[debug] Loaded Chained actions:
.-------------------------------------+--------------------------------------.
| Path Spec | Private |
+-------------------------------------+--------------------------------------+
| /chain_base/*/* | /chain_base (1) |
| | => GET /any_priority_chain (1) |
| /chain_base/*/*/* | /chain_base (1) |
| | -> /link_int (Int) |
| | => /any_priority_link (1) |
| /chain_base/*/*/*/* | /chain_base (1) |
| | -> /link_int_int (Int,Int) |
| | => /any_priority_link2 (1) |
| /chain_base/*/*/*/*/* | /chain_base (1) |
| | -> /link_tuple (Tuple[Int,Int,Int]) |
| | => /any_priority_link3 (1) |
| /chain_base/*/*/* | /chain_base (1) |
| | -> /link_any (1) |
| | => /any_priority_link_any (1) |
| /chain_base/*/*/*/*/*/* | /chain_base (1) |
| | -> /link_tuple (Tuple[Int,Int,Int]) |
| | -> /link2_int (UserId) |
| | => GET /finally (Int) |
| /chain_base/*/*/*/*/*/... | /chain_base (1) |
| | -> /link_tuple (Tuple[Int,Int,Int]) |
| | -> /link2_int (UserId) |
| | => GET /finally2 (...) |
| /chain_base/*/* | /chain_base (1) |
| | => /int_priority_chain (Int) |
| /chain_base/*/*/* | /chain_base (1) |
| | -> /link_int (Int) |
| | => /int_priority_link (Int) |
| /chain_base/*/*/*/* | /chain_base (1) |
| | -> /link_int_int (Int,Int) |
| | => /int_priority_link2 (Int) |
| /chain_base/*/*/*/*/* | /chain_base (1) |
| | -> /link_tuple (Tuple[Int,Int,Int]) |
| | => /int_priority_link3 (Int) |
| /chain_base/*/*/* | /chain_base (1) |
| | -> /link_any (1) |
| | => /int_priority_link_any (Int) |
'-------------------------------------+--------------------------------------'
As you can see the same general path could be matched by various action chains. In this case
the rule described in the previous section should be followed, which is that L<Catalyst>
will start with the last defined action and work upward. For example the action C<int_priority_chain>
would be checked before C<any_priority_chain>. The same applies for actions that are midway links
in a longer chain. In this case C<link_int> would be checked before C<link_any>. So as always we
recommend that you place you priority or most constrained actions last and you least or catch-all
actions first.
Although this reverse order checking may seen counter intuitive it does have the added benefit that
when inheriting controllers any new actions added would take check precedence over those in your
parent controller or consumed role.
Please note that your declared type constraint names will now appear in the debug console.
=head1 Author
John Napiorkowski L<jjnapiork@cpan.org|email:jjnapiork@cpan.org>
=cut
( run in 0.648 second using v1.01-cache-2.11-cpan-39bf76dae61 )