SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Webアプリケーションフレームワーク「Catalyst」入門

初めてのCatalyst入門(7)
モデルを使ったプログラミング

ブックマークの情報をデータベースに保存する


コントローラの実装

 ブックマークアプリケーションでは次のパスを定義します。ブックマークエントリのIDをパスに含めたいので、Chainedアクションを使って実装してみましょう。

定義するURLのパス
パス 説明
/ ブックマークエントリの一覧表示
/add ブックマークエントリの追加
/*/jump 登録されたURLへリダイレクト
/*/edit ブックマークエントリの編集
/*/delete ブックマークエントリの削除

 まずは一覧表示とエントリの追加を行うアクションを見ていきます。

[リスト9]Root.pmの一部(一覧表示/エントリ追加)
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回の記事を参照ください。

[リスト10]Root.pmの一部(エントリURLへのリダイレクト/編集/削除)
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メソッドで呼び出された場合に使用しています。

次のページ
ブックマークアプリケーションの実行

この記事は参考になりましたか?

Webアプリケーションフレームワーク「Catalyst」入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 花田 善仁(ハナダ ヨシヒト)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4788 2010/06/21 19:56

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー