Catalyst::Wiki
/best practices
Catalyst best practices
Follow the Catalyst diet: thin controller, fat model.
Decouple as much as possible. If you have to fire up your web application in order to test database insertion, that's wrong. Build the model so that you can use Perl one liners to manipulate data through it. For example, with MojoMojo, you can do:
perl -Ilib -MMojoMojo -le' MojoMojo->model("DBIC::Person")->find({login=>"admin"})->update({pass=>"wonky"}) '
Use the recommended modules and plugins
See recommended plugins.
$c->stash Sets and Gets
Set a Single Value
Two ways to store things in $c->stash:
- $c->stash(key => value)
- $c->stash->{key} = $value
NOTE: Bruce Lee prefers the first method in general for putting things in the stash. The second approach may occasionally be useful in hairy (long value) situations (e.g. where you want a specific part of a complex data structure).
Stash Multiple Values
The first approach above leads naturally into setting multiple values in one $c->stash call. For example,
$c->stash(
sex => 'female',
look => 'good',
weather => 'hot',
swim => 'now',
);
Get Your Stash
my $stuff = $c->stash->{medicine};
Don't Use BindLex
The lead author says don't use it, so don't. It was one of those things that looked good at the time, but wasn't.
Using Catalyst::Controller::action_for combined with $c->uri_for
There are two forms of $c->uri_for():
Arguments: ( $action, \@captures?, @args?, \%query_values? )
NOTE:
$controller->action_forreturns a catalyst action object. This is the more flexible because of object introspection advantages (see #catalyst for explanation).Example:
$c->uri_for( $c->controller('YourController')->action_for('action_method') );Arguments: ( $path, @args?, \%query_values? )
In this case, the $path is not an object, thus it can't introspect nor have a dynamic URI.
Using Catalyst::Controller::uri_for_action()
Starting Catalyst 5.8.1 there is a new short and reliable way to generate dynamic URIs.
Arguments: ( $path, \@captures?, @args?, \%query_values? )
The first argument is a path to the action method which is converted into an action object and handed over to
uri_for.Example:
$c->uri_for_action('yourcontroller/action_method')Arguments: ( $action, \@captures?, @args?, \%query_values? )
In this case all arguments are directoy passed to
uri_for
Internationalisation
Translation strings
Assume that the translated strings will return back information "as-is" without any markup. Therefore, you will need to escape characters based on where the text is being used:
Html
For TT, pass through the html filter:
<p>[% c.loc("Some text that might have < or > in it") | html %]</p>
Javascript strings
Pass through escape_js_string filter. You can use single or double quotes for the string assignment.
< script >
var string = '[% c.loc("May have single quotes or \ in it") | escape_js %]';
< /script >
(Note: we've put spaces around the < and > to avoid actually defining script tags)
escape_js can be defined in MyApp::View::TT with:
use Template::Filters; # Need to use, so that we can have access to $Template::Filters::FILTERS
$Template::Filters::FILTERS->{escape_js} = \&escape_js_string;
sub escape_js_string {
my $s = shift;
$s =~ s/(\\|'|"|\/)/\\$1/g;
return $s;
};
HTML elements with javascript snippets
Pass through the escape_js_string filter, then the html filter:
< select onclick=" alert('[% c.loc("May have all sorts of things in it") | escape_js | html %]') ">
(Extra space added to stop intepretation of select tag)
It is best to use double quotes for the attribute value and then single quotes for the javascript strings.