Loadable Traits for Catalyst Components
Over the past few months we've developed a loadable traits system for Catalyst components. Components are Models, Views, and Controllers.
Traits are Moose::Roles, that are applied to classes dynamically.
Roles for Controllers, with actual actions, are possible thanks to Tomas Doran's (t0m) and Florian Ragwitz's (rafl) work on MooseX::MethodAttributes.
Loadable traits support is provided by CatalystX::Component::Traits, based on Jonathan Rockway's (jrockway) work on MooseX::Traits.
An Example
Let's make a simple Model and some traits for it, so you can see how you might make use of this feature in your own projects.
package SampleApp::Model::Fortune; use Moose; use namespace::autoclean; extends 'Catalyst::Model'; with 'CatalystX::Component::Traits'; has '+_trait_merge' => (default => 1); __PACKAGE__->config->{traits} = [ 'OffensiveToo' ]; has fortune_command => (is => 'rw', lazy_build => 1); has fortune_command_opts => (is => 'rw', lazy_build => 1); sub get_fortune { my $self = shift; my $command = $self->fortune_command . ' ' . $self->fortune_command_opts; my $output = qx{$command}; chomp $output; return $output; } sub _build_fortune_command { 'fortune' } sub _build_fortune_command_opts { '' } __PACKAGE__->meta->make_immutable; package SampleApp::TraitFor::Model::Fortune::Russian; use Moose::Role; use namespace::autoclean; has percent_russian => (is => 'rw', default => 100); around fortune_command_opts => sub { my ($next, $self) = (shift, shift); my $dbs = $self->percent_russian . '% ru' . ' ' . (100 - $self->percent_russian) . '% /usr/share/games/fortunes'; return $self->$next(@_) . ' ' . $dbs; }; package SampleApp::TraitFor::Model::Fortune::Offensive; use Moose::Role; use namespace::autoclean; around fortune_command_opts => sub { my ($next, $self) = (shift, shift); return '-o ' . $self->$next(@_); }; package SampleApp::TraitFor::Model::Fortune::OffensiveToo; use Moose::Role; use namespace::autoclean; around fortune_command_opts => sub { my ($next, $self) = (shift, shift); my $opts = $self->$next(@_); $opts =~ s/-o //; # if Offensive trait is enabled, edit it out return "-a $opts"; }; 1;
Notice we turned on the "TRAIT MERGING" in CatalystX::Component::Traits
feature, and we set a default list of traits to include (OffensiveToo
.)
An action to make use of our new Model:
sub index :Path :Args(0) { my ($self, $c) = @_; $c->res->content_type('text/plain; charset=utf-8'); $c->res->body($c->model('Fortune')->get_fortune); }
Now, suppose in production you don't want your customers to see offensive fortunes, and you want 50% of the fortunes to be in Russian.
Just put the following into the .conf
:
<Model::Fortune> traits -OffensiveToo traits Russian percent_russian 50 </Model::Fortune>
We turned off the OffensiveToo
trait, added the Russian
trait and set an
attribute that was defined in a trait directly from the config file.
Hopefully this demonstrates some of the power of using Moose::Roles in your Catalyst applications.
See also the Catalyst::ActionRole::
namespace for other awesome applications
of Moose::Roles.
Components that use Loadable Traits
Catalyst::Model::DBIC::Schema
The model for using DBIx::Class in Catalyst has the following traits available on CPAN:
- Catalyst::TraitFor::Model::DBIC::Schema::Caching
-
For caching the results of queries.
- Catalyst::TraitFor::Model::DBIC::Schema::Replicated
-
For quering replicated MySQL databases.
- Catalyst::TraitFor::Model::DBIC::Schema::QueryLog
-
DBIx::Class::QueryLog support, for analyzing query performance.
CatalystX::SimpleLogin
A reusable login/logout component for Catalyst that is injected through the Plugin list. It has the following traits available on CPAN:
- CatalystX::SimpleLogin::TraitFor::Controller::Login::Logout
-
Adds logout support.
- CatalystX::SimpleLogin::TraitFor::Controller::Login::WithRedirect
-
Combines with Catalyst::ActionRole::NeedsLogin to mark actions as requiring a login and redirecting back to the originally requested page.
- CatalystX::SimpleLogin::TraitFor::Controller::Login::RenderAsTTTemplate
-
Provides a Template template for rendering the login form, for use with Catalyst::View::TT.
AUTHOR
Caelum: Rafael Kitover <rkitover@cpan.org>