Stories
Slash Boxes
Comments

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of LTjake (4001)

Monday November 27, 2006
11:32 PM

Catalyst Tip: Generic Base Controllers

[ #31738 ]

So, you want to write a generic base controller for some set of actions? Great! Want to use Chained actions for nicer looking URLs? Fantastic!

Let's presume you're writing a generic account admin controller. Your URL-space might look like:

/admin/account/
account list
/admin/account/1/
account view
/admin/account/1/update
account update

Currently, you have a couple of options in order to make this a reality:

1) Action-specific configs

Catalyst's configurability is extremely granular -- you can set specific attributes as configuration parameters for any given action.

package MyApp::Controller::Admin::Account;

use strict;
use warnings;

use base 'Catalyst::Controller';

__PACKAGE__->config( actions => {
    instance => { PathPart => 'admin/account' },
    list     => { PathPart => 'admin/account' }
} );

sub list     : Chained('/') Args(0) { die "index of accounts" }
sub instance : Chained('/') CaptureArgs(1) { } # do something with $c->req->captures->[ 0 ]
sub view     : Chained('instance') PathPart('') Args(0) { die "view account" }
sub update   : Chained('instance') PathPart Args(0) { die "update account" }

1;

In the above example we're explicitly setting the PathPart for the list and instance actions -- However, it's not quite fully generic.

2) Create our own attribute

We'll create an attribute that will expose a controller's path_prefix to any action -- aptly named PathPrefix.

package MyApp::Controller::Admin::Account;

use strict;
use warnings;

use base 'Catalyst::Controller';

sub _parse_PathPrefix_attr {
    my ( $self, $c, $name, $value ) = @_;
    return PathPart => $self->path_prefix;
}

sub list     : Chained('/') PathPrefix Args(0) { die "index of accounts" }
sub instance : Chained('/') PathPrefix CaptureArgs(1) { } # do something with $c->req->captures->[ 0 ]
sub view     : Chained('instance') PathPart('') Args(0) { die "view account" }
sub update   : Chained('instance') PathPart Args(0) { die "update account" }

1;

Now that's better -- except for that pesky sub. Well, you're in luck -- PathPrefix is now in the current Catalyst::Runtime branch. Our code is now even simpler:

package MyApp::Controller::Admin::Account;

use strict;
use warnings;

use base 'Catalyst::Controller';

sub list     : Chained('/') PathPrefix Args(0) { die "index of accounts" }
sub instance : Chained('/') PathPrefix CaptureArgs(1) { } # do something with $c->req->captures->[ 0 ]
sub view     : Chained('instance') PathPart('') Args(0) { die "view account" }
sub update   : Chained('instance') PathPart Args(0) { die "update account" }

1;

As I've stated, Catalyst is extremely configurable. Let's say you don't like "admin/account" as the path? No Problem!

package MyApp::Controller::Admin::Account;

use strict;
use warnings;

use base 'Catalyst::Controller';

__PACKAGE__->config( path => 'foo/bar' );

sub list     : Chained('/') PathPrefix Args(0) { die "index of accounts" }
sub instance : Chained('/') PathPrefix CaptureArgs(1) { } # do something with $c->req->captures->[ 0 ]
sub view     : Chained('instance') PathPart('') Args(0) { die "view account" }
sub update   : Chained('instance') PathPart Args(0) { die "update account" }

1;

All of the actions will now start with "/foo/bar/"!

Happy Hacking.

Special thanks to mst for being my editor and sanity checker.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.