« 早起き過ぎ | Home | 2006 夜景 新宿駅東口 »

[Catalyst]   Chained ActionでスマートなURL

Chained Actionを使った例でこんな記事がありました。

/user/
    ユーザー一覧
/user/add
    ユーザー追加
/user/[ユーザー名]
    [ユーザー名]の詳細
/user/[ユーザー名]/edit
    [ユーザー名]の編集
/user/[ユーザー名]/delete
    [ユーザー名]の削除

というURL構成を再現するのに

package MyApp::Controller::User;

use strict;
use warnings;
use base 'Catalyst::Controller';

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

sub root : Chained('/') PathPrefix CaptureArgs(0) {
    my ( $self, $c ) = @_;
}

sub instance : Chained('root') PathPart('') CaptureArgs(1) {
    my ( $self, $c ) = @_;

    $c->stash->{user} = $c->req->captures->[0];
}

sub list : Chained('root') PathPart('') Args(0) {
    my ( $self, $c ) = @_;

    $c->res->body( ref($self) . '->list' );
}

sub add : Chained('root') PathPart Args(0) {
    my ( $self, $c ) = @_;

    $c->res->body( ref($self) . '->add' );
}

sub view : Chained('instance') PathPart('') Args(0) {
    my ( $self, $c ) = @_;

    my $user = $c->stash->{user};
    $c->res->body( ref($self) . "->view $user" );
}

sub edit : Chained('instance') PathPart Args(0) {
    my ( $self, $c ) = @_;

    my $user = $c->stash->{user};
    $c->res->body( ref($self) . "->edit $user" );
}

sub delete : Chained('instance') PathPart Args(0) {
    my ( $self, $c ) = @_;

    my $user = $c->stash->{user};
    $c->res->body( ref($self) . "->delete $user" );
}

1;

非常に便利。
肝は_parse_PathPrefix_attrでPathPrefixという独自アトリビュートを作ってpath_prefixにディスパッチするところ。

さらにこんなことをしたい場合は

/user/[ユーザー名]/bookmark
    [ユーザー名]のブックマーク一覧
/user/[ユーザー名]/bookmark/add
    [ユーザー名]のブックマーク追加
/user/[ユーザー名]/bookmark/[ブックマーク]
    [ユーザー名]のブックマーク[ブックマーク]の詳細
/user/[ユーザー名]/bookmark/[ブックマーク]/edit
    [ユーザー名]のブックマーク[ブックマーク]の編集
/user/[ユーザー名]/bookmark/[ブックマーク]/delete
    [ユーザー名]のブックマーク[ブックマーク]の削除

こうすればいいかと。

package MyApp::Controller::User::Bookmark;

use strict;
use warnings;
use base 'Catalyst::Controller';

sub root : Chained('/user/instance') PathPart('bookmark') CaptureArgs(0) {
    my ( $self, $c ) = @_;
}

sub instance : Chained('root') PathPart('') CaptureArgs(1) {
    my ( $self, $c ) = @_;

    $c->stash->{bookmark} = $c->req->captures->[1];
}

sub list : Chained('root') PathPart('') Args(0) {
    my ( $self, $c ) = @_;

    $c->res->body( ref($self) . '->list' );
}

sub add : Chained('root') PathPart Args(0) {
    my ( $self, $c ) = @_;

    $c->res->body( ref($self) . '->add' );
}

sub view : Chained('instance') PathPart('') Args(0) {
    my ( $self, $c ) = @_;

    my $user     = $c->stash->{user};
    my $bookmark = $c->stash->{bookmark};

    $c->res->body( ref($self) . "->view $user / $bookmark" );
}

sub edit : Chained('instance') PathPart Args(0) {
    my ( $self, $c ) = @_;

    my $user     = $c->stash->{user};
    my $bookmark = $c->stash->{bookmark};

    $c->res->body( ref($self) . "->edit $user / $bookmark" );
}

sub delete : Chained('instance') PathPart Args(0) {
    my ( $self, $c ) = @_;

    my $user     = $c->stash->{user};
    my $bookmark = $c->stash->{bookmark};

    $c->res->body( ref($self) . "->delete $user / $bookmark" );
}

1;

追記: typo訂正

Trackbacks:

このエントリーのトラックバックURL:

コメントを投稿