2005年07月10日

use Catalyst qw(初挑戦);

Catalystとは!?

Perl界でじわじわもりあがってきてるMVCウェブフレームワーク Catalyst を試してみた。

Catalyst は Maypole というフレームワークの後継らしい。MaypoleのページのCatalystの説明によると、

Catalyst is a new, elegant web application framework for Perl. It is based on Maypole and adds many features from Ruby-on-Rails, Struts, Spring and Tomcat in a new and innovative way.

と言われていて、いろいろな既存プロジェクトからエッセンスをもらったフレームワークなんだね。

こいつの大きな特徴は、いくつかのコマンドを打つだけでアプリの原型(スケルトン)を作成してくれること。しかも TT や Class::DBI、Ajax なJavaScript などもプラグインで対応していて、同じフレームワークである Sledge や CGI::Application よりもモダンな印象をうける。後述するAttributeを使ったアクション定義や、テストサーバー機能もクールです。

以下、作業メモ。

インストール

試したのは PowerbookG4(10.3.9)。CPAN で一式をインストールします。つい先日 HD を初期化した後だったというのもあるけど、大量に関連モジュールを入れてくれました。

% sudo perl -MCPAN -e shell
install Bundle::Catalyst

追記:最近ちょっと違う。こちらを参照されたし

たりないモジュールがあればあとで入れるとして、とりあえず進む。

スケルトン作成

まず、作業ディレクトリで catalyst.pl をたたきます。

$ catalyst.pl Hello         ← 引数でアプリのPackage名を指定。ディレクトリを切る場合はTomi::Hogeとか。
created "Hello"            ← そのPackage名でフォルダを作ってくれます
created "Hello/script"
created "Hello/lib"
created "Hello/root"
created "Hello/t"
created "Hello/t/M"
created "Hello/t/V"
created "Hello/t/C"
created "Hello/lib/Hello"
created "Hello/lib/Hello/M"
created "Hello/lib/Hello/V"
created "Hello/lib/Hello/C"
created "Hello/lib/Hello.pm"    ← これがコントローラ
created "Hello/Build.PL"
created "Hello/Makefile.PL"
created "Hello/README"
created "Hello/Changes"
created "Hello/t/01app.t"
created "Hello/t/02pod.t"
created "Hello/t/03podcoverage.t"
created "Hello/script/hello_cgi.pl"        ← このへん、専用のヘルパースクリプト
created "Hello/script/hello_fastcgi.pl"
created "Hello/script/hello_server.pl"
created "Hello/script/hello_test.pl"
created "Hello/script/hello_create.pl"

追記:最近は M、V、C でなくて Model、View、Controller となります。

あとは MVC をそれぞれ作成していくのだけど、Catalyst の売りである Class::DBI とか Template との連携などはヘルパースクリプトを利用してお決まりのものを作らせてしまうのが Catalyst 流。ビューで Template-Toolkit を使う場合はこんな感じ。

$ cd Hello          ← 作成されたディレクトリに移動
$ script/hello_create.pl view TT TT        ← ビューを作成、TTというクラス名で、TTを利用するの意
created "/Users/sherlock/Sites/public_html/cata/Hello/script/../lib/Hello/V/TT.pm"
created "/Users/sherlock/Sites/public_html/cata/Hello/script/../t/V/TT.t"

ほかにも、help をみるといろんなことができるらしい。

$ script/hello_create.pl -help
Usage:
    hello_create.pl [options] model|view|controller name [helper] [options]

     Options:
       -help    display this help and exits

     Examples:
       hello_create.pl controller My::Controller
       hello_create.pl view My::View
       hello_create.pl view MyView TT
       hello_create.pl view TT TT
       hello_create.pl model My::Model
       hello_create.pl model SomeDB CDBI dbi:SQLite:/tmp/my.db
       hello_create.pl model AnotherDB CDBI dbi:Pg:dbname=foo root 4321

     See also:
       perldoc Catalyst::Manual
       perldoc Catalyst::Manual::Intro
コントローラの構造

Hello/lib/Hello.pm をカスタマイズしていきます。POD ドキュメントを消してみるとこんな感じのシンプルなコントローラです。

package Hello;

use strict;
use Catalyst qw/-Debug/;

our $VERSION = '0.01';

Hello->config( name => 'Hello' );

Hello->setup;

sub default : Private {
    my ( $self, $c ) = @_;
    $c->res->output('Congratulations, Hello is on Catalyst!');
}

1;

部位ごとの説明。

まず、4行目の use Catalyst 部について。
渡すオプションによって、Catalystの基本機能を決定します。ハイフン付きのものはオプション指定で、ついてないのは利用するプラグイン。例えば、デバッグオプションがONで、Catalyst::Plugin::FormValidator を使うぞという時はこうする。

use Catalyst qw(
    -Debug
    FormValidator
);

今回は -Debug オプションしか使わない。

次に、8行目のconfig設定部について。
ここには、ハッシュの形で好きなものを登録でき、それはコントローラ内のサブルーチンから参照できます。たいていは TT で利用するグローバルな変数とかテンプレートのパスとかを設定。今回はとりあえずそのまま。

Hello->config( 
    name => 'Hello',
);

12行目以下には、コントローラを記述していく。
つまりアクセス URL 形式とサブルーチンを対応させるのだけど、コントローラというのが「属性」を付けた複数のサブルーチンというのが Catalyst の面白いところ。

たとえば、http://パス/hogehoge/ という形式でアクセスされたときに実行したい処理は、以下のように記述する。

sub hogehoge : Global {
   # 処理...
}

パスと処理のマッピングを XML などの別ファイルにしないところがいかにもPerl的な気がする。 関数もしくは変数 : 属性 という、あまり利用されていないけどちゃんと予約されている正規の構文を使ってくるあたりもヒジョーにマニアックでよいです。

関数名 : 属性のいろいろ

この 関数名 : 属性 の指定方法には以下のようなものがあります。

リクエストパス系

関数名 : 属性 意味
aaaaa : Global その関数名でアクセスされた場合に内容を実行。 例だとhttp://パス/aaaaa/の時に実行。関数名部分は何でもよい。ただし当然ながらURLとして問題ないものに限る。URLのPATHINFO部分もPerlの関数名も大文字小文字を区別するので、AaaとaaAは異なる。
eeeee : Regex('^step\d$') Globalに似てるが、リクエストパスを正規表現で指定。 例だとhttp://パス/step1/とかhttp://パス/step2/で実行される。関数名部分は自由。

リクエストパスに一致する関数が複数指定指定されていた場合、上のもの一つだけ実行されるみたいです。

デフォルト処理系

関数名 : 属性 意味
default : Private どれにも一致しないリクエストパスの場合呼び出されるデフォルト処理関数。トップページの処理など。
begin : Private 指定した場合、すべてのリクエストパス系処理の最初に必ず呼び出される
auto : Private 指定した場合、すべてのリクエストパス系処理の最初に必ず呼び出される(beginの後)
end : Private 指定した場合、すべてのリクエストパス系処理の最後に必ず呼び出される

順番などは、ここがわかりやすいです

$c について

さてつぎに、サブルーチン内処理ですが、

sub default : Private {
    my ($self, $c) = @_;
    $c->res->output('Hello');
}

みたいにして、第二引数で入ってくる $c を利用して Catalyst のオブジェクトを操作。詳しくはみてないけどよく使うのは以下のようなもの。

$c 内容
$c->config 設定値へのハッシュリファレンス。$c->config->{'name'}; などとしてアクセス
$c->stash オブジェクト間で利用する変数格納用ハッシュリファレンス。$c->stash->{'message'} = "こんにちは!"; などとしておいてほかのオブジェクトから利用
$c->req->param GET・POSTの値へのハッシュリファレンス。$c->req->param('zip'); などとしてアクセス
$c->req->arguments PATHINFOをスラッシュで区切ったリストリファレンス。http://パス/hoge/a/b/c/ のとき $c->req->arguments->[1] は b
$c->req->snippets 実行サブルーチンの属性がRegexで、正規表現内でメモリかっこを利用した場合、結果が入るリストリファレンス。hoge : Regex('^step(\d+)$') のとき http://パス/step50/ でアクセスすると $c->req->snippets->[0] は 50
$c->res->output 引数をそのまま出力。$c->res->output('Hello!'); など
$c->res->redirect 引数にリダイレクト。$c->res->redirect('/'); など
$c->res->content_type $c->res->content_type("text/html; charset=EUC-JP"); など
$c->res->forward ほかのサブルーチン・オブジェクトに処理を投げる。$c->res->forward('hoge'); など。
Template-Toolkitを利用するにはstashを利用して、
$c->stash->{template} = 'page2.html';
$c->forward('Hello::V::TT');
のようにする。
$c->log $c->log->debug("message!"); とするとログに文字を吐ける。
テストアプリケーション

以上をふまえて、 1)まずシンプルに Hello と page2/ へのリンクがあるページを開き、 2)page2/ にアクセスするとテンプレートを利用してページを表示する、 というサンプルアプリを作りたい場合、コントローラにしてみると、以下のようになる。

package Hello;

use strict;
use Catalyst qw(
    -Debug
    );

our $VERSION = '0.01';

Hello->config( name => 'Hello', );
Hello->setup;

sub default : Private {
    my ($self, $c) = @_;
    $c->res->output('Hello World! <a href="page2/">go to page</a>.');
}

sub page2 : Global {
    my ($self, $c) = @_;
    $c->stash->{message} = 'Page2';
    $c->stash->{template} = 'page2.html';
    $c->forward('Hello::V::TT');
}

テンプレートファイルは Hello/root 以下に保存するのがおすすめらしい。
Hello/root/page2.html

<center>[% message %]</center>

これで完成。

テストサーバー機能

すごいのは、テスト用の httpd 機能があること。script/hello_server.pl をたたくと、ポート3000番で待機する。

$ script/hello_server.pl
[Sun Jul 10 22:47:47 2005] [catalyst] [debug] Debug messages enabled
[Sun Jul 10 22:47:48 2005] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
[Sun Jul 10 22:47:48 2005] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
[Sun Jul 10 22:47:48 2005] [catalyst] [debug] Found home xxxxxxxxxxxxxxxxxxx
[Sun Jul 10 22:47:48 2005] [catalyst] [debug] Loaded components:
.=----------------------------------------------------------------------------=.
| Hello::V::TT                                                                |
'=----------------------------------------------------------------------------='

[Sun Jul 10 22:47:48 2005] [catalyst] [debug] Loaded private actions:
.=-------------------------------------+--------------------------------------=.
| Private                              | Class                                 |
|=-------------------------------------+--------------------------------------=|
| /default                             | Hello                                 |
| /page2                               | Hello                                 |
'=-------------------------------------+--------------------------------------='

[Sun Jul 10 22:47:48 2005] [catalyst] [debug] Loaded public actions:
.=-------------------------------------+--------------------------------------=.
| Public                               | Private                               |
|=-------------------------------------+--------------------------------------=|
| /page2                               | /page2                                |
'=-------------------------------------+--------------------------------------='

[Sun Jul 10 22:47:48 2005] [catalyst] [info] Application powered by Catalyst 5.30
You can connect to your server at http://localhost:3000/

こんな感じでログを吐きつつ起動。以下、アクセスごとにログが吐かれる。

ブラウザで http://localhost:3000/ にアクセスすると。。。テストできます!。こりゃ便利!


TrackBack

Comments

コメントをどうぞ


冨田尚樹
Naoki Tomita
loading from twitter
たぶん人気なもの
del.icio.us/scrap
今日のCPANモジュール
とみた広報
Syndicate this site
Syndicate this site
あわせて読みたい なかのひと