NAME
CatalystX::Declare::Keyword::Action - Declare Catalyst Actions
SYNOPSIS
use CatalystX::Declare;
controller MyApp::Web::Controller::Example {
# chain base action with path part setting of ''
# body-less actions don't do anything by themselves
action base as '' under '/';
# simple end-point action
action controller_class is final under base {
$ctx->response->body( 'controller: ' . ref $self );
}
# chain part actions can have arguments
action str (Str $string) under base {
$ctx->stash(chars => [split //, $string]);
}
# and end point actions too, of course
action uc_chars (Int $count) under str is final {
my $chars = $ctx->stash->{chars};
...
}
# you can use a shortcut for multiple actions with
# a common base
under base {
# this is an endpoint after base
action normal is final;
# the final keyword can be used to be more
# visually explicit about end-points
final action some_action { ... }
}
# of course you can also chain to external actions
final action some_end under '/some/controller/some/action';
}
DESCRIPTION
This handler class provides the user with action
, final
and under
keywords. There are multiple ways to define actions to allow for greater freedom of expression. While the parts of the action declaration itself do not care about their order, their syntax is rather strict.
You can choose to separate syntax elements via ,
if you think it is more readable. The action declaration
action foo is final under base;
is parsed in exactly the same way if you write it as
action foo, is final, under base;
Basic Action Declaration
The simplest possible declaration is
action foo;
This would define a chain-part action chained to nothing with the name foo
and no arguments. Since it isn't followed by a block, the body of the action will be empty.
You will automatically be provided with two variables: $self
is, as you might expect, your controller instance. $ctx
will be the Catalyst context object. Thus, the following code would stash the value returned by the get_item
method:
action foo {
$ctx->stash(item => $self->get_item);
}
Setting a Path Part
As usual with Catalyst actions, the path part (the public name of this part of the URI, if you're not familiar with the term yet) will default to the name of the action itself (or more correctly: to whatever Catalyst defaults).
To change that, use the as
option:
under something {
action base as ''; # <empty>
action something as 'foo/bar'; # foo/bar
action barely as bareword; # bareword
}
Chaining Actions
Currently, CatalystX::Declare is completely based on the concept of chained actions. Every action you declare is chained or private. You can specify the action you want to chain to with the under
option:
action foo; # chained to nothing
action foo under '/'; # also chained to /
action foo under bar; # chained to the local bar action
action foo under '/bar/baz'; # chained to baz in /bar
under
is also provided as a grouping keyword. Every action inside the block will be chained to the specified action:
under base {
action foo { ... }
action bar { ... }
}
You can also use the under
keyword for a single action. This is useful if you want to highlight a single action with a significant diversion from what is to be expected:
action base under '/';
under '/the/sink' is final action foo;
final action bar under base;
final action baz under base;
Instead of the under
option declaration, you can also use a more english variant named chains to
. While under
might be nice and concise, some people might prefer this if they confuse under
with the specification of a public path part. The argument to chains to
is the same as to under
:
action foo chains to bar;
action foo under bar;
By default all actions are chain-parts, not end-points. If you want an action to be picked up as end-point and available via a public path, you have to say so explicitely by using the is final
option:
action base under '/';
action foo under base is final; # /base/foo
You can also drop the is
part of the is final
option if you want:
under base, final action foo { ... }
You can make end-points more visually distinct by using the final
keyword instead of the option:
action base under '/';
final action foo under base; # /base/foo
And of course, the final
, under
and action
keywords can be used in combination whenever needed:
action base as '' under '/';
under base {
final action list; # /list
action load;
under load {
final action view; # /list/load/view
final action edit; # /list/load/edit
}
}
There is also one shorthand alternative for declaring chain targets. You can specify an action after a <-
following the action name:
action base under '/';
final action foo <- base; # /base/foo
Arguments
You can use signatures like you are use to from MooseX::Method::Signatures to declare action parameters. The number of arguments will be used during dispatching. Dispatching by type constraint is planned but not yet implemented.
The signature follows the action name:
# /foo/*/*/*
final action foo (Int $year, Int $month, Int $day);
If you are using the shorthand definition, the signature follows the chain target:
# /foo/*
final action foo <- base ($x) under '/' { ... }
Parameters may be specified on chain-parts and end-points:
# /base/*/foo/*
action base (Str $lang) under '/';
final action page (Int $page_num) under base;
Named parameters will be populated with the values in the query parameters:
# /view/17/?page=3
final action view (Int $id, Int :$page = 1) under '/';
Your end-points can also take an unspecified amount of arguments by specifying an array as a variable:
# /find/some/deep/path/spec
final action find (@path) under '/';
Validation
Currently, when the arguments do not fit the signature because of a Moose validation error, the response body will be set to Bad Request
and the status to 400
.
Actions and Method Modifiers
Method modifiers can not only be applied to methods, but also to actions. There is no way yet to override the attributes of an already established action via modifiers. However, you can modify the method underlying the action.
The following code is an example role modifying the consuming controller's base
action:
use CatalystX::Declare;
component_role MyApp::Web::ControllerRole::RichBase {
before base (Object $ctx) {
$ctx->stash(something => $ctx->model('Item'));
}
}
Note that you have to specify the $ctx
argument yourself, since you are modifying a method, not an action.
Any controller having a base
action (or method, for this purpose), can now consume the RichBase
role declared above:
use CatalystX::Declare;
controller MyApp::Web::Controller::Foo
with MyApp::Web::Controller::RichBase {
action base as '' under '/';
action show, final under base {
$ctx->response->body(
$ctx->stash->{something}->render,
);
}
}
ROLES
METHODS
These methods are implementation details. Unless you are extending or developing CatalystX::Declare, you should not be concerned with them.
parse
Object->parse (Object $ctx, Str :$modifier?, Int :$skipped_declarator = 0)
A hook that will be invoked by MooseX::Declare when this instance is called to handle syntax. It will parse the action declaration, prepare attributes and add the actions to the controller.
SEE ALSO
AUTHOR
See "AUTHOR" in CatalystX::Declare for author information.
LICENSE
This program is free software; you can redistribute it and/or modify it under the same terms as perl itself.