my $last = pop(@chain);
foreach my $action ( @chain ) {
my @args;
- if (my $cap = $action->attributes->{Captures}) {
+ if (my $cap = $action->attributes->{CaptureArgs}) {
@args = splice(@captures, 0, $cap->[0]);
}
local $c->request->{arguments} = \@args;
my $parent = "DUMMY";
my $curr = $endpoint;
while ($curr) {
- if (my $cap = $curr->attributes->{Captures}) {
+ if (my $cap = $curr->attributes->{CaptureArgs}) {
unshift(@parts, (("*") x $cap->[0]));
}
if (my $pp = $curr->attributes->{PartPath}) {
my @rows;
foreach my $p (@parents) {
my $name = "/${p}";
- if (my $cap = $p->attributes->{Captures}) {
+ if (my $cap = $p->attributes->{CaptureArgs}) {
$name .= ' ('.$cap->[0].')';
}
unless ($p eq $parents[0]) {
}
my @try_actions = @{$children->{$try_part}};
TRY_ACTION: foreach my $action (@try_actions) {
- if (my $capture_attr = $action->attributes->{Captures}) {
+ if (my $capture_attr = $action->attributes->{CaptureArgs}) {
my @captures;
my @parts = @parts; # localise
- # strip Captures into list
+ # strip CaptureArgs into list
push(@captures, splice(@parts, 0, $capture_attr->[0]));
# try the remaining parts against children of this action
($self->{actions} ||= {})->{'/'.$action->reverse} = $action;
- unless ($action->attributes->{Captures}) {
+ unless ($action->attributes->{CaptureArgs}) {
unshift(@{ $self->{endpoints} ||= [] }, $action);
}
my $parent = "DUMMY";
my $curr = $action;
while ($curr) {
- if (my $cap = $curr->attributes->{Captures}) {
+ if (my $cap = $curr->attributes->{CaptureArgs}) {
return undef unless @captures >= $cap->[0]; # not enough captures
unshift(@parts, splice(@captures, -$cap->[0]));
}
of the chain specifies how many arguments it gets through the C<Args>
attribute. C<:Args(0)> would be none at all, C<:Args> without an integer
would be unlimited. The path parts that aren't endpoints are using
-C<Captures> to specify how many parameters they expect to receive. As an
+C<CaptureArgs> to specify how many parameters they expect to receive. As an
example setup:
package MyApp::Controller::Greeting;
use base qw/ Catalyst::Controller /;
# this is the beginning of our chain
- sub hello : PathPart('hello') Chained('/') Captures(1) {
+ sub hello : PathPart('hello') Chained('/') CaptureArgs(1) {
my ( $self, $c, $integer ) = @_;
$c->stash->{ message } = "Hello ";
$c->stash->{ arg_sum } = $integer;
}
- # this is our endpoint, because it has no :Captures
+ # this is our endpoint, because it has no :CaptureArgs
sub world : PathPart('world') Chained('hello') Args(1) {
my ( $self, $c, $integer ) = @_;
$c->stash->{ message } .= "World!";
As you can see, Catalyst only deals with chains as whole path and
builds one for each endpoint, which are the actions with C<:Chained>
-but without C<:Captures>.
+but without C<:CaptureArgs>.
Let's assume this application gets a request at the path
C</hello/23/world/12>, what happens then? First, Catalyst will dispatch
to the C<hello> action and pass the value C<23> as argument to it after
-the context. It does so because we have previously used C<:Captures(1)>
+the context. It does so because we have previously used C<:CaptureArgs(1)>
to declare that it has one path part after itself as it's argument. We
told Catalyst that this is the beginning of the chain by specifying
C<:Chained('/')>. Also note that instead of saying C<:PathPart('hello')>
After C<hello> has run, Catalyst goes on to dispatch to the C<world>
action. This is the last action to be called, as Catalyst knows this
-is an endpoint because we specified no C<:Captures> attribute. Nevertheless
+is an endpoint because we specified no C<:CaptureArgs> attribute. Nevertheless
we specify that this action expects an argument, but at this point we're
using C<:Args(1)> to do that. We could also have said C<:Args> or leave
it out alltogether, which would mean this action gets all arguments that
C</wiki/FooBarPage/rev/23/view>. This chain can be easily built with
these actions:
- sub wiki : PathPart('wiki') Chained('/') Captures(1) {
+ sub wiki : PathPart('wiki') Chained('/') CaptureArgs(1) {
my ( $self, $c, $page_name ) = @_;
# load the page named $page_name and put the object
# into the stash
}
- sub rev : PathPart('rev') Chained('wiki') Captures(1) {
+ sub rev : PathPart('rev') Chained('wiki') CaptureArgs(1) {
my ( $self, $c, $revision_id ) = @_;
# use the page object in the stash to get at it's
# revision with number $revision_id
If you want, for example, to have actions for the public paths
C</foo/12/edit> and C</foo/12>, just specify two actions with
C<:PathPart('foo')> and C<:Chained('/')>. The handler for the former
-path needs a C<:Captures(1)> attribute and a endpoint with
+path needs a C<:CaptureArgs(1)> attribute and a endpoint with
C<:PathPart('edit')> and C<:Chained('foo')>. For the latter path give
the action just a C<:Args(1)> to mark it as endpoint. This sums up to
this debugging output:
For example:
# in MyApp::Controller::Foo
- sub bar : Chained Captures(1) { ... }
+ sub bar : Chained CaptureArgs(1) { ... }
# in MyApp::Controller::Foo::Bar
sub baz : Chained('.') Args(1) { ... }
action chains directly to C</>, so the above chain comes out as end
product.
-=item Captures
+=item CaptureArgs
Also has to be specified for every part of the chain that is not an
endpoint. With this attribute Catalyst knows how many of the following
parts of the path (separated by C</>) this action wants to captures as
-it's arguments. If it doesn't expect any, just specify C<:Captures(0)>.
+it's arguments. If it doesn't expect any, just specify C<:CaptureArgs(0)>.
The captures get passed to the action's C<@_> right after the context,
but you can also find them as array reference in
C<$c-E<gt>request-E<gt>captures-E<gt>[$level]>. The C<$level> is the
level of the action in the chain that captured the parts of the path.
An action that is part of a chain (read: that has a C<:Chained> attribute)
-but has no C<:Captures> attribute is treated by Catalyst as a chain end.
+but has no C<:CaptureArgs> attribute is treated by Catalyst as a chain end.
=item Args
By default, endpoints receive the rest of the arguments in the path. You
can tell Catalyst through C<:Args> explicitly how many arguments your
-endpoint expects, just like you can with C<:Captures>. Note that this
+endpoint expects, just like you can with C<:CaptureArgs>. Note that this
also influences if this chain is invoked on a request. A chain with an
endpoint specifying one argument will only match if exactly one argument
exists in the path.
leaving it out alltogether: The chain is matched independent of the number
of path parts after the endpoint.
-Just like with C<:Captures>, the arguments get passed to the action in
+Just like with C<:CaptureArgs>, the arguments get passed to the action in
C<@_> after the context object. They can also be reached through
C<$c-E<gt>request-E<gt>arguments>.
#
# Simple parent/child action test
#
-sub foo :PathPart('chained/foo') :Captures(1) :Chained('/') { }
+sub foo :PathPart('chained/foo') :CaptureArgs(1) :Chained('/') { }
sub endpoint :PathPart('end') :Chained('/action/chained/foo') :Args(1) { }
#
# Parent/child test with two args each
#
-sub foo2 :PathPart('chained/foo2') :Captures(2) :Chained('/') { }
+sub foo2 :PathPart('chained/foo2') :CaptureArgs(2) :Chained('/') { }
sub endpoint2 :PathPart('end2') :Chained('/action/chained/foo2') :Args(2) { }
#
# Relative specification of parent action
#
-sub bar :PathPart('chained/bar') :Chained('/') :Captures(0) { }
+sub bar :PathPart('chained/bar') :Chained('/') :CaptureArgs(0) { }
sub finale :PathPart('') :Chained('bar') :Args { }
#
# three chain with concurrent endpoints
#
-sub one :PathPart('chained/one') :Chained('/') :Captures(1) { }
-sub two :PathPart('two') :Chained('/action/chained/one') :Captures(2) { }
+sub one :PathPart('chained/one') :Chained('/') :CaptureArgs(1) { }
+sub two :PathPart('two') :Chained('/action/chained/one') :CaptureArgs(2) { }
sub three_end :PathPart('three') :Chained('two') :Args(3) { }
sub one_end :PathPart('chained/one') :Chained('/') :Args(1) { }
sub two_end :PathPart('two') :Chained('one') :Args(2) { }
#
# Controller -> subcontroller -> controller
#
-sub pcp1 :PathPart('chained/pcp1') :Chained('/') :Captures(1) { }
+sub pcp1 :PathPart('chained/pcp1') :Chained('/') :CaptureArgs(1) { }
sub pcp3 :Chained('/action/chained/foo/pcp2') :Args(1) { }
#
# Dispatch on capture number
#
-sub multi_cap1 :PathPart('chained/multi_cap') :Chained('/') :Captures(1) { }
-sub multi_cap2 :PathPart('chained/multi_cap') :Chained('/') :Captures(2) { }
+sub multi_cap1 :PathPart('chained/multi_cap') :Chained('/') :CaptureArgs(1) { }
+sub multi_cap2 :PathPart('chained/multi_cap') :Chained('/') :CaptureArgs(2) { }
sub multi_cap_end1 :PathPart('baz') :Chained('multi_cap1') :Args(0) { }
sub multi_cap_end2 :PathPart('baz') :Chained('multi_cap2') :Args(0) { }
# Priority: Slurpy args vs. chained actions
#
sub priority_a1 :PathPart('chained/priority_a') :Chained('/') :Args { }
-sub priority_a2 :PathPart('chained/priority_a') :Chained('/') :Captures(1) { }
+sub priority_a2 :PathPart('chained/priority_a') :Chained('/') :CaptureArgs(1) { }
sub priority_a2_end :PathPart('end') :Chained('priority_a2') :Args(1) { }
#
# Priority: Fixed args vs. chained actions
#
sub priority_b1 :PathPart('chained/priority_b') :Chained('/') :Args(3) { }
-sub priority_b2 :PathPart('chained/priority_b') :Chained('/') :Captures(1) { }
+sub priority_b2 :PathPart('chained/priority_b') :Chained('/') :CaptureArgs(1) { }
sub priority_b2_end :PathPart('end') :Chained('priority_b2') :Args(1) { }
#
#
# Optional PathPart test -> /chained/optpp/*/opt_pathpart/*
#
-sub opt_pp_start :Chained('/') :PathPart('chained/optpp') :Captures(1) { }
+sub opt_pp_start :Chained('/') :PathPart('chained/optpp') :CaptureArgs(1) { }
sub opt_pathpart :Chained('opt_pp_start') :Args(1) { }
#
# Optional Args *and* PathPart -> /chained/optall/*/oa/...
#
-sub opt_all_start :Chained('/') :PathPart('chained/optall') :Captures(1) { }
+sub opt_all_start :Chained('/') :PathPart('chained/optall') :CaptureArgs(1) { }
sub oa :Chained('opt_all_start') { }
#
# the ParentChain controller chains to this action by
# specifying :Chained('.')
#
-sub parentchain :Chained('/') :PathPart('chained/parentchain') :Captures(1) { }
+sub parentchain :Chained('/') :PathPart('chained/parentchain') :CaptureArgs(1) { }
#
# This is just for a test that a loose end is not callable
#
-sub loose :Chained :PathPart('chained/loose') Captures(1) { }
+sub loose :Chained :PathPart('chained/loose') CaptureArgs(1) { }
#
# Forwarding out of the middle of a chain.
#
-sub chain_fw_a :Chained :PathPart('chained/chain_fw') :Captures(1) {
+sub chain_fw_a :Chained :PathPart('chained/chain_fw') :CaptureArgs(1) {
$_[1]->forward( '/action/chained/fw_dt_target' );
}
sub chain_fw_b :Chained('chain_fw_a') :PathPart('end') :Args(1) { }
#
# Detaching out of the middle of a chain.
#
-sub chain_dt_a :Chained :PathPart('chained/chain_dt') :Captures(1) {
+sub chain_dt_a :Chained :PathPart('chained/chain_dt') :CaptureArgs(1) {
$_[1]->detach( '/action/chained/fw_dt_target' );
}
sub chain_dt_b :Chained('chain_dt_a') :PathPart('end') :Args(1) { }
#
# Simple chains with auto actions returning 1 and 0
#
-sub foo : Chained PathPart('chained/autochain1') Captures(1) { }
-sub bar : Chained PathPart('chained/autochain2') Captures(1) { }
+sub foo : Chained PathPart('chained/autochain1') CaptureArgs(1) { }
+sub bar : Chained PathPart('chained/autochain2') CaptureArgs(1) { }
#
# Detaching out of an auto action.
#
-sub dt1 : Chained PathPart('chained/auto_detach') Captures(1) { }
+sub dt1 : Chained PathPart('chained/auto_detach') CaptureArgs(1) { }
#
# Forwarding out of an auto action.
#
-sub fw1 : Chained PathPart('chained/auto_forward') Captures(1) { }
+sub fw1 : Chained PathPart('chained/auto_forward') CaptureArgs(1) { }
#
# Target for dispatch and forward tests.
sub barend : Chained('.') Args(1) { }
-sub crossloose : Chained PathPart('chained/auto_cross') Captures(1) { }
+sub crossloose : Chained PathPart('chained/auto_cross') CaptureArgs(1) { }
1;
# Redispatching between controllers that are not in a parent/child
# relation. This is the root.
#
-sub cross1 :PathPart('chained/cross') :Captures(1) :Chained('/') { }
+sub cross1 :PathPart('chained/cross') :CaptureArgs(1) :Chained('/') { }
1;
#
# Root for a action in a "parent" controller
#
-sub higher_root :PathPart('chained/higher_root') :Chained('/') :Captures(1) { }
+sub higher_root :PathPart('chained/higher_root') :Chained('/') :CaptureArgs(1) { }
#
# Parent controller -> this subcontroller -> parent controller test
#
-sub pcp2 :Chained('/action/chained/pcp1') :Captures(1) { }
+sub pcp2 :Chained('/action/chained/pcp1') :CaptureArgs(1) { }
#
# Controllers not in parent/child relation. This tests the end.
# as it should.
#
-sub first : PathPart('chained/passedargs/a') Chained('/') Captures(1) {
+sub first : PathPart('chained/passedargs/a') Chained('/') CaptureArgs(1) {
my ( $self, $c, $arg ) = @_;
$c->stash->{ passed_args } = [ $arg ];
}
-sub second : PathPart('b') Chained('first') Captures(1) {
+sub second : PathPart('b') Chained('first') CaptureArgs(1) {
my ( $self, $c, $arg ) = @_;
push @{ $c->stash->{ passed_args } }, $arg;
}
#
# The first three-chain test tries to call the action with :Args(1)
- # specification. There's also a one action with a :Captures(1)
+ # specification. There's also a one action with a :CaptureArgs(1)
# attribute, that should not be dispatched to.
#
{
#
# This is the second three-chain test, it goes for the action that
# handles "/one/$cap/two/$arg1/$arg2" paths. Should be the two action
- # having :Args(2), not the one having :Captures(2).
+ # having :Args(2), not the one having :CaptureArgs(2).
#
{
my @expected = qw[
}
#
- # Last of the three-chain tests. Has no concurrent action with :Captures
+ # Last of the three-chain tests. Has no concurrent action with :CaptureArgs
# and is more thought to simply test the chain as a whole and the 'two'
- # action specifying :Captures.
+ # action specifying :CaptureArgs.
#
{
my @expected = qw[