コントローラの実装
ブックマークアプリケーションでは次のパスを定義します。ブックマークエントリのIDをパスに含めたいので、Chainedアクションを使って実装してみましょう。
| パス | 説明 |
| / | ブックマークエントリの一覧表示 |
| /add | ブックマークエントリの追加 |
| /*/jump | 登録されたURLへリダイレクト |
| /*/edit | ブックマークエントリの編集 |
| /*/delete | ブックマークエントリの削除 |
まずは一覧表示とエントリの追加を行うアクションを見ていきます。
package Bookmark::Controller::Root;
# 省略
# (1)一覧表示
sub index :Path :Args(0) {
my ( $self, $c ) = @_;
$c->stash->{entries} = [$c->model('BookmarkDB::Entry')->all];
}
# (2)ブックマークエントリの追加
sub add :Local :Args(0) {
my ( $self, $c ) = @_;
if ($c->req->method eq 'POST') {
# パラメータの取得
my $url = $c->req->params->{url};
my $title = $c->req->params->{title};
my $comment = $c->req->params->{comment};
# パラメータのチェック
if ($url eq '' || $title eq '') {
$c->stash->{template} = 'invalid_params.tt';
} else {
# データベースに新しいエントリを登録
$c->model('BookmarkDB::Entry')->create({
url => $url,
title => $title,
comment => $comment
});
$c->res->redirect('/', 303);
}
}
}
(1)一覧表示
indexアクションでは、データベースからすべてのレコードを取得し、配列としてStashに渡しています。index.ttをテンプレートとして、エントリのURL一覧情報をレンダリングします。
(2)ブックマークエントリの追加
addアクションでは、HTTPのPOSTメソッドで呼び出された場合にパラメータから受け取ったURLなどの情報をデータベースに登録し、GETメソッドなどで呼び出された場合には、add.ttをテンプレートとしてレスポンスを表示します。
Entryテーブルの定義では、URLとTitleはNOT NULL制約がついているので、パラメータから受け取った値が空の場合には、invalid_params.ttを表示するようにしています。
そして、URLとTitleが空でない場合には$c->model('BookmarkDB::Entry')->create()メソッドに各カラムの名前とパラメータの値をセットしてデータベースに登録しています。登録に成功したらindexアクションにリダイレクトしています。
次にエントリIDにより指定される、ブックマークエントリの編集、削除、リダイレクトなどを実装したアクションを見ていきます。この部分はChainedアクションを使用しています。Chainedアクションについては第5回の記事を参照ください。
package Bookmark::Controller::Root;
# 省略
# (1)パスに含まれるエントリIDをStashに登録
sub capture_entry :Chained('/') :PathPart('') :CaptureArgs(1) {
my ( $self, $c, $entry_id ) = @_;
if (my $entry = $c->model('BookmarkDB::Entry')->find($entry_id)) {
$c->stash->{entry} = $entry;
} else {
$c->stash->{template} = 'not_found.tt';
}
}
# (2)エントリのURLにリダイレクト
sub jump_entry :Chained('capture_entry') :PathPart('jump') :Args(0) {
my ( $self, $c ) = @_;
my $entry = $c->stash->{entry};
# counterを1増やして更新
$entry->counter($entry->counter + 1);
$entry->update;
$c->res->redirect($entry->url);
}
# (3)エントリの編集
sub edit_entry :Chained('capture_entry') :PathPart('edit') :Args(0) {
my ( $self, $c ) = @_;
my $entry = $c->stash->{entry};
if ($c->req->method eq 'POST') {
my $url = $c->req->params->{url};
my $title = $c->req->params->{title};
my $comment = $c->req->params->{comment};
if ($url eq '' || $title eq '') {
$c->stash->{template} = 'invalid_params.tt';
} else {
$entry->url($url);
$entry->title($title);
$entry->comment($comment);
$entry->update;
$c->res->redirect('/', 303);
}
}
}
# (4)エントリの削除
sub delete_entry :Chained('capture_entry') :PathPart('delete') :Args(0) {
my ( $self, $c ) = @_;
my $entry = $c->stash->{entry};
if ($c->req->method eq 'POST') {
# データベースから削除
$entry->delete;
$c->res->redirect('/', 303);
}
}
(1)パスに含まれるエントリIDをStashに登録
capture_entryアクションでは、パスに含まれるエントリIDをキーにして、データベースから検索した結果が存在すればStashに登録しています。存在しないエントリIDが渡された場合には、not_found.ttをテンプレートとしてレスポンスを表示します。
(2)エントリのURLにリダイレクト
jump_entryアクションでは、エントリとして登録したURLにリダイレクトするのですが、その際に何回選択したかを表すcounterの値を1だけ増やしています。Stashから取得したEntryオブジェクトに値を更新した場合、それをデータベースに反映させるには、updateメソッドを呼び出します。
(3)エントリの削除
delete_entryアクションではエントリの削除を実装してます。POSTメソッドで呼び出された場合に限り、Stashに登録されているEntryオブジェクトに対して削除を実行するdeleteメソッドを呼び出し、GETメソッドなどから呼び出された場合には、削除の確認を行うためにdelete_entry.ttをレンダリングして表示します。
エントリの編集を扱うedit_entryアクションについてはサンプルコードをご覧ください。
ビューの実装
ブックマークアプリケーションではCatalyst::View::TTのテンプレートファイルを6つ作成しました。紙面の都合上、具体的なコード解説は省きますので、詳細は記事に添付されているサンプルファイルを参照してください。
| テンプレートファイル名 | 説明 |
| index.tt | 一覧表示用テンプレート |
| add.tt | エントリの追加フォームを表示するテンプレート |
| edit_entry.tt | エントリの編集フォームを表示するテンプレート |
| delete_entry.tt | エントリの削除フォームを表示するテンプレート |
| invalid_params.tt | 不正なパラメータを受け取った場合に表示するテンプレート |
| not_found.tt | 指定されたエントリが存在しない場合に表示するテンプレート |
この中で、add.tt、edit_entry.tt、delete_entry.ttはHTTPのGETメソッドで呼び出された場合に使用しています。
