[Catalyst] My experience porting to CataMoose

Sebastian Willert willert at gmail.com
Tue May 19 01:38:48 GMT 2009


On Fri, 2009-05-15 at 15:09 +0100, Tomas Doran wrote:
> Sebastian Willert wrote:
> > I'll give it a try this weekend, having 5.80004 is enough
> > encouragement ;)
> > 
> > I guess the main body should go into "Extending Catalyst" while having a
> > pointer to this in "Upgrading"?

OK, after stumbling through Moose-ifying my first Catalyst app I figured
a larger manual would be in order. Here is my first stab at creating
such a thing. Please bear in mind that English is not my native language
and this is my first dab into Moose so this document is probably rife
with factual and grammatical errors.

Without further ado, I hope a few people find this helpful.

Cheers,
  Sebastian




-------------- next part --------------
=head1 NAME

Catalyst::Manual::CatalystAndMoose - How Catalyst 5.8+ and Moose relate

=head1 DESCRIPTION

Since version 5.8 the core of Catalyst is based on L<Moose>. Although the
developers went through great lengths to allow for a seamless transition,
there are still a few rough edges when trying to exploit the power of L<Moose>
in your Catalyst application.

This document provides you with a short overview of common caveats and best
practices to use L<Moose>-based classes within Catalyst.

=head1 THE CONTEXT CLASS

A Moose-ified version of the context class should look like this:

 package MyApp;

 use Moose;
 use Catalyst;

 $app->config( name => 'MyApp' );
 $app->setup(
   # your roles and plugins
 );

 # method modifiers must be created after setup because otherwise they will
 # conflict with plugin overrides

 after 'finalize' => sub{
   my $c = shift;
   $c->log->info( 'done!' );
 }

You should also be aware, that roles in C<< $c->setup >> are applied after the
last plugin with all the benefits of using a single C<< with() >> statement in
an ordinary L<Moose> class and that your class is automatically made immutable
for you after the call to setup (method modifiers in your class will work,
though).

CAVEAT: using roles in C<< $c->setup >> was implemented in Catalyst version
5.80004. In prior versions you might get away with

 after 'setup_plugins' => sub{ with(
   # your roles
 )};

 $app->setup(
   # your plugins
 );

but this is discouraged and you should upgrade to 5.80004 anyway, because it
fixes a few important regression against 5.71

[Q: COULD THIS BE USED TO RESOLVE CONFLICTS IN ROLES?].

=head2 ACCESSORS

Most of the request specific attributes like C<$c-&gt;stash>,
C<$c-&gt;request> and C<$c-&gt;response> have been converted to L<Moose>
attributes but without type constraints, attribute helpers or builder
methods. This ensures that Catalyst 5.8 is fully backwards compatible to
applications using the published API of Catalyst 5.7 but slightly limits
the gains that could be had by wielding the full power of L<Moose> attributes.

Most of the accessors to information gathered during compile time is managed
by C<Catalyst::ClassData>, which is a L<Moose>-aware version of
L<Class::Data::Inheritable> but not compatible with L<MooseX::ClassAttribute>.


=head2 ROLES AND METHOD MODIFIERS

Since the release of Catalyst version 5.8 the only reason for creating a
Catalyst extension as a plugin is to provide backward compatibility to
applications still using version 5.7 but even then you should consider
building your plugin using L<Moose> and take advantage of
L<Moose::Manual::MethodModifiers|method modifiers> instead of overriding
methods to alter Catalyst's request lifecycle behavior.

If backward compatibility is of no concern to you, you could as easily rewrite
your plugins as roles and enjoy all the benefits of automatic method
re-dispatching of C<< before >> and C<< after >> method modifiers, naming
conflict detecting and generally cleaner code.

Plugins and roles should never use

  after 'setup' => sub { ... } # wrong

but rely on

  after 'setup_finalize' => sub { ... } # this will work

to run their own setup code if needed. If they need to influence the setup
process itself, they can modify C<< setup_dispatcher() >>,
C<< setup_engine()>>, C<< setup_stats() >>, C<< setup_components() >>
and C<< setup_actions() >>, but this should be done with due consideration and
as late as possible.

=head1 CONTROLLERS

To activate Catalyst's action attributes, Moose-ified controller classes
need to extend L<Catalyst::Controller> at compile time before the actions
themselves are declared:

  package Catalyst::Controller::Root;

  use Moose;
  BEGIN{
    extends 'Catalyst::Controller';
    with(
      # your controller roles
    );
  }

[MORE TO BE DONE!]


More information about the Catalyst mailing list