NAME
Catalyst::ActionRole::MethodSignatureDependencyInjection - Experimental Action Signature Dependency Injection
SYNOPSIS
Attribute syntax:
package MyApp::Controller
use base 'Catalyst::Controller';
sub test_model :Local :Does(MethodSignatureDependencyInjection)
ExecuteArgsTemplate($Req, $Res, $BodyData, $BodyParams, $QueryParams, Model::A, Model::B)
{
my ($self, $c, $Req, $Res, $Data, $Params, $Query, $A, $B) = @_;
}
Prototype syntax
package MyApp::Controller
use base 'Catalyst::Controller';
no warnings::illegalproto;
sub test_model($Req, $Res, $BodyData, $BodyParams, $QueryParams, Model::A, Model::B)
:Local :Does(MethodSignatureDependencyInjection) UsePrototype(1)
{
my ($self, $c, $Req, $Res, $Data, $Params, $Query, $A, $B) = @_;
}
WARNING
Lets you declare required action dependencies via the a subroutine attribute and additionally via the prototype (if you dare)
This is a poorly documented, early access prototype. The author reserves the right to totally change everything and potentially disavow all knowledge of it. Only report bugs if you are capable of offering a patch and discussion.
Please note if any of the declared dependencies return undef, that will cause the action to not match. This could probably be better warning wise...
DESCRIPTION
Catalyst when dispatching a request to an action calls the Action::Class execute method with the following arguments ($self, $c, @args). This you likely already know (if you are a <Catalyst> programmer).
This action role lets you describe an alternative 'template' to be used for what arguments go to the execute method. This way instead of @args you can get a model, or a view, or something else. The goal of this action role is to make your action bodies more concise and clear and to have your actions declare what they want.
Additionally, when we build these arguments, we also check their values and require them to be true during the match/match_captures phase. This means you can actually use this to control how an action is matched.
There are two ways to use this action role. The default way is to describe your execute template using the 'ExecuteArgsTemplate' attribute. The second is to enable UsePrototype (via the UsePrototype(1) attribute) and then you can declare your argument template via the method prototype. You will of course need to use 'no warnings::illegalproto' for this to work. The intention here is to work toward something that would play nice with a system for method signatures like Kavorka.
If this sounds really verbose it is. This distribution is likely going to be part of something larger that offers more sugar and less work, just it was clearly also something that could be broken out and hacked pn separately. If you use this you might for example set this action role in a base controller such that all your controllers get it (one example usage).
Please note that you must still access your arguments via @_
, this is not a method signature framework.
DEPENDENCY INJECTION
You define your execute arguments as a positioned list (for now). The system recognizes the following 'built ins' (you always get $self and $c, as you do in the current system).
$req
The current Catalyst::Request
$res
The current Catalyst::Response
$args
The current an arrayref of the current args
@args
An array of the current args. Only makes sense if this is the last specified argument.
$arg0 .. $argN
One of the indexed args, where $args0 => $args[0];
$bodyData
$c->req->body_data
$bodyParams
$c->req->body_parameters
$QueryParams
$c->req->query_parameters
Accessing Components
You can request a Catalyst component (a model, view or controller). You do this via [Model||View||Controller]::$component_name. For example if you have a model that you'd normally access like this:
$c->model("Schema::User");
You would say "Model::Schema::User". For example:
ExecuteArgsTemplate(Model::Schema::User)
Or via the prototype
sub myaction(Model::Schema::User) ...
You can also pass arguments to your models. For example:
ExecuteArgsTemplate(Model::UserForm<Model::User>)
same as $c->model('UserForm', $c->model('User'));
Integration with Function::Parameters
For those of you that would like to push the limits even harder, we have experimental support for Function::Parameters. You may use like in the following example.
package MyApp::Controller::Root;
use base 'Catalyst::Controller';
use Function::Parameters({
method => {defaults => 'method'},
action => {
attributes => ':method :Does(MethodSignatureDependencyInjection) UsePrototype(1)',
shift => '$self',
check_argument_types => 0,
strict => 0,
default_arguments => 1,
}});
action test_model($c, $res, Model::A $A, Model::Z $Z)
:Local
{
# ...
$res->body(...);
}
method test($a) {
return $a;
}
Please note that currently you cannot use the 'parameterized' syntax for component injection (no Model::Model::Z support).
SEE ALSO
Catalyst::Action, Catalyst, warnings::illegalproto.
AUTHOR
John Napiorkowski email:jjnapiork@cpan.org
COPYRIGHT & LICENSE
Copyright 2015, John Napiorkowski email:jjnapiork@cpan.org
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 312:
Deleting unknown formatting code A<>