Catalyst Plugins, Writing
From Dev411: The Code Wiki
This page provides some tips for writing Catalyst plugins.
| Table of contents |
Tests
An easy way to write tests for plugins is to create a Catalyst::Test TestApp. See Catalyst::Plugin::DefaultEnd, Catalyst::Plugin::I18N, etc. for examples. ##live.t where ## is 04 seems to be a common name for a test using TestApp so your distribution ends up with the following files:
t/04live.t t/lib/TestApp.pm
To run the test use:
prove -v t/04live.t
Prerequisites, Checking for
Sometimes your plugin will rely on the usage of other plugins. You can use $c->can to check for those plugins.
# From Catalyst::Plugin::UploadProgress
sub setup {
my $c = shift;
$c->NEXT::setup(@_);
[...]
unless ( $c->can('cache') && $c->can('session') ) {
Catalyst::Exception->throw(
message => '<Plugin Name> requires cache and session plugins.'
);
}
}
Error at Startup
You can thrown an exception during start up if there's an error by using an eval cage and then setting $c->log->debug if $c->debug is set. Here's an example:
# From Class::Model::CDBI
eval { $self->loader( Class::DBI::Loader->new(%$self) ) };
if ($@) {
Catalyst::Exception->throw( message => $@ );
}
else {
$c->log->debug(
'Loaded tables "' . join( ' ', $self->loader->tables ) . '"' )
if $c->debug;
}
# From Catalyst::Model::DBI
sub new {
my ( $self, $c ) = @_;
$self = $self->NEXT::new($c);
$self->{namespace} ||= ref $self;
$self->{additional_base_classes} ||= ();
eval {
$self->dbh(
DBI->connect(
$self->{dsn},
$self->{user},
$self->{password},
$self->{options}
)
);
};
if ($@) { $c->log->debug( qq{Couldn't connect to the database "$@"} ) if $c->debug }
else { $c->log->debug ( q{Connected to the database} ) if $c->debug; }
return $self;
}
Context Namespace, Cleaner
Catalyst puts plugin methods in the $c context namespace like $c->foo, however sometimes it is cleaner to have a plugin method like $c->myplugin->foo. This can be accomplished by separating the plugin into two modules, a plugin and a plugin wrapper. Although plugins are not typically written this way, it can be done. The plugin wrapper could be:
package Catalyst::Plugin::MyPlugin;
use strict;
use base 'Class::Data::Inheritable';
use MyPlugin;
__PACKAGE__->mk_classdata('myplugin');
sub prepare {
my $c = shift;
$c = $c->NEXT::prepare( @_ );
$c->mailer( MyPlugin->new( $c ) );
return $c;
}
1;
Private Namespace Plugins
Catalyst automatically finds plugins in the Catalyst::Plugin:: namespace. You can use the following to add plugins in your own namespace.
# From #catalyst irc channel
miyagawa: If you want plugins for your own app, you could
sub MyApp::setup_plugins {
my $c = shift;
$c->NEXT::setup_plugins(@_);
# now push your own plugins on @ISA
}
SVN Patches
If you want to create a patch for an existing Catalyst plugin, see the page on SVN Patches
