to hook onto to provide functionality.
These can be applied to your models/views/controllers, and your application
-class. Please see the sections below for special notes and caveats, and
-the L<Moose::Manual::Roles> for more information about roles in general.
-
-=head3 In your application class
-
-It should be noted that when applying roles to your application class, that
-you should B<not> wrap methods provided by L<Catalyst> until B<after> you have
-run C<< __PACKAGE__->setup >>, as your class does not inherit from any of your
-plugins until the setup method is run.
-
-With Catalyst 5.80004, it is possible to include Roles in the plugin list, and
-these roles will be applied to your application class immediately after
-'traditional' plugins have been composed into your application class'
-inheritance hierarchy.
-
-=head3 In controllers
-
-Method modifiers on controller actions will work as expected (either in your
-controllers, or when composed from roles) in Catalyst 5.80003 and above.
-
-It is possible to have action methods with attributes inside Moose roles, using
-the trait introduced in L<MooseX::MethodAttributes> version 0.12, example:
-
- package MyApp::ControllerRole;
- use Moose::Role -traits => 'MethodAttributes';
-
- sub foo : Local {
- my ($self, $c) = @_;
- ...
- }
+class, and shipped to CPAN.
+Please see L<Catalyst::Manual::CatalystAndMoose> for specific information
+about using Roles in combination with Catalyst, and L<Moose::Manual::Roles>
+for more information about roles in general.
=head2 Inheritance and overriding methods
-When overriding a method, keep in mind that some day additionall
+When overriding a method, keep in mind that some day additional
arguments may be provided to the method, if the last parameter is not
a flat list. It is thus better to override a method by shifting the
invocant off of C<@_> and assign the rest of the used arguments, so
sub foo : Local Bar('Baz') {
my ($self, $c) = @_;
- my $attributes =
- $self->action_for('foo')->attributes;
+ my $attributes = $self->action_for('foo')->attributes;
$c->res->body($attributes->{Bar}[0] );
}
creation. Please refer to the modules documentation for usage
information.
-=head2 Component configuration
+=head2 Component Configuration
At creation time, the class configuration of your component (the one
available via C<$self-E<gt>config>) will be merged with possible
configuration settings from the applications configuration (either
-directly or via config file). This is then stored in the controller
-object's hash reference. So, if you read possible configurations like:
+directly or via config file). This is done by Catalyst, and the
+correctly merged configuration is passed to your component's
+constructor (i.e. the new method).
+
+Ergo, if you define an accessor for each configuration value
+that your component takes, then the value will be automatically stored
+in the controller object's hash reference, and available from the
+accessor.
- my $model_name = $controller->{model_name};
+The C<config> accessor always only contains the original class configuration
+and you B<MUST NEVER> call $self->config to get your component configuration,
+as the data there is likely to be a subset of the correct config.
-you will get the right value. The C<config> accessor always only
-contains the original class configuration and must not be used for
-component configuration.
+For example:
-You are advised to create accessors on your component class for your
-configuration values. This is good practice and makes it easier to
-capture configuration key typos. You can do this with the
-C<mk_ro_accessors> method provided to L<Catalyst::Component> via
-L<Class::Accessor::Fast>:
+ package MyApp
+ use Moose;
+
+ extends 'Catalyst';
- use base 'Catalyst::Controller';
- __PACKAGE__->mk_ro_accessors('model_name');
...
- my $model_name = $controller->model_name;
+
+ __PACKAGE__->config(
+ 'Controller::Foo' => { some_value => 'bar' },
+ );
+
+ ...
+
+ package MyApp::Controller::Foo;
+ use Moose;
+ use namespace::autoclean;
+ BEGIN { extends 'Catalyst::Controller' };
+
+ has some_value ( is => 'ro', required => 1 );
+
+ sub some_method {
+ my $self = shift;
+ return "the value of 'some_value' is " . $self->some_value;
+ }
+
+ ...
+
+ my $controller = $c->controller('Foo');
+ warn $controller->some_value;
+ warn $controller->some_method;
=head1 IMPLEMENTATION
subclass:
package Catalyst::Action::MyFoo;
- use strict;
-
+ use Moose;
+ use namespace::autoclean;
use MRO::Compat;
- use base 'Catalyst::Action';
+ extends 'Catalyst::Action';
sub execute {
my $self = shift;
Mondays:
package Catalyst::Action::OnlyMondays;
- use strict;
-
+ use Moose;
+ use namespace::autoclean;
use MRO::Compat;
- use base 'Catalyst::Action';
+ extends 'Catalyst::Action';
sub match {
my $self = shift;
classes that you want to specify more conveniently, you can implement
a component base class providing an attribute handler.
-For further information on action classes, please refer to
+It is not possible to use multiple action classes at once, however
+L<Catalyst::Controller::ActionRole> allows you to apply L<Moose Roles|Moose::Role>
+to actions.
+
+For further information on action classes and roles, please refer to
L<Catalyst::Action> and L<Catalyst::Manual::Actions>.
=head2 Component base classes
will use C<MyApp::Action::Bar> as action class.
- package MyApp::Base::Controller::FullClass; use strict; use base
- 'Catalyst::Controller';
+ package MyApp::Base::Controller::FullClass;
+ use Moose;
+ use namespace::autoclean;
+ BEGIN { extends 'Catalyst::Controller'; }
sub _parse_FullClass_attr {
my ($self, $app_class, $action_name, $value, $attrs) = @_;
Catalyst attribute:
package MyApp::Controller::Foo;
- use strict;
- use base 'MyApp::Base::Controller::FullClass';
+ use Moose;
+ use namespace::autoclean;
+ BEGIN { extends 'MyApp::Base::Controller::FullClass'; }
sub foo : Local FullClass('MyApp::Action::Bar') { ... }
be inherited by the subclasses. Consider this controller base class:
package MyApp::Base::Controller::ModelBase;
- use strict;
- use base 'Catalyst::Controller';
+ use Moose;
+ use namespace::autoclean;
+
+ BEGIN { extends 'Catalyst::Controller'; }
sub list : Chained('base') PathPart('') Args(0) {
my ($self, $c) = @_;
my $condition = $self->{model_search_condition} || {};
my $attrs = $self->{model_search_attrs} || {};
$c->stash(rs => $model->search($condition, $attrs);
- }
+ }
sub load : Chained('base') PathPart('') CaptureArgs(1) {
my ($self, $c, $id) = @_;
my $model = $c->model( $self->{model_name} );
$c->stash(row => $model->find($id));
- }
+ }
1;
This example implements two simple actions. The C<list> action chains
with some custom actions by sub-classing it:
package MyApp::Controller::Foo;
- use strict;
- use base 'MyApp::Base::Controller::ModelBase';
+ use Moose;
+ use namespace::autoclean;
+
+ BEGIN { extends 'MyApp::Base::Controller::ModelBase'; }
__PACKAGE__->config( model_name => 'DB::Foo',
model_search_condition=> { is_active => 1 },
Here is some example code for a fictional view:
- package CatalystX::View::MyView;
- use strict;
- use base 'Catalyst::View';
+ package Catalyst::View::MyView;
+ use Moose;
+ use namespace::autoclean;
+
+ extends 'Catalyst::View';
sub process {
my ($self, $c) = @_;
B<Please do not> release Catalyst extensions as plugins only to
provide some functionality application wide. Design it as a controller
-base class or another suiting technique with a smaller scope, so that
+base class or another better suited technique with a smaller scope, so that
your code only influences those parts of the application where it is
needed, and namespace clashes and conflicts are ruled out.
package CatalystX::UriforUndefWarning;
use Moose::Role;
- use namespace::clean -except => 'meta';
+ use namespace::autoclean;
after 'uri_for' => sub {
my ($c, $arg) = @_;
if (!blessed($_[0]) || !$_[0]->isa('Catalyst::Action'));
return $uri;
};
+
+Note that Catalyst will load any Moose Roles in the plugin list,
+and apply them to your application class.
=head2 Factory components with COMPONENT()
Here is a stub C<COMPONENT> method:
package CatalystX::Component::Foo;
- use strict;
- use base 'Catalyst::Component';
-
- use MRO::Compat;
+ use Moose;
+ use namespace::autoclean;
+
+ extends 'Catalyst::Component';
sub COMPONENT {
my $class = shift;
For more information, please see
L<Catalyst::Component/"COMPONENT($c,$arguments)">.
+=head2 Applying roles to parts of the framework
+
+L<CatalystX::RoleApplicator> will allow you to apply Roles to
+the following classes:
+
+=over
+
+=item Request
+
+=item Response
+
+=item Engine
+
+=item Dispatcher
+
+=item Stats
+
+=back
+
+These roles can add new methods to these classes, or wrap preexisting methods.
+
+The namespace for roles like this is C<Catalyst::TraitFor::XXX::YYYY>.
+
+For an example of a CPAN component implemented in this manor, see
+L<Catalyst::TraitFor::Request::BrowserDetect>.
+
=head1 SEE ALSO
L<Catalyst>, L<Catalyst::Manual::Actions>, L<Catalyst::Component>
-=head1 AUTHOR
-
-Robert Sedlacek C<< <rs@474.at> >>
+=head1 AUTHORS
-Jonathan Rockway C<< <jrockway@cpan.org> >>
+Catalyst Contributors, see Catalyst.pm
-=head1 LICENSE AND COPYRIGHT
+=head1 COPYRIGHT
-This document is free, you can redistribute it and/or modify it under
+This library is free software. You can redistribute it and/or modify it under
the same terms as Perl itself.
=cut
+