Catalyst覚え書き1
Catalyst 覚え書き1
インストール
<URL:http://search.cpan.org/~jrockway/Catalyst-Manual-5.700701/lib/Catalyst/Manual/Intro.pod#Install>によれば、インストールは面倒なので、
<URL:http://www.shadowcatsystems.co.uk/static/cat-install>にあるPerlのスクリプトを実行して、Catalyst::Develをインストールすれば良いとあり、つまり
# perl cat-install
# perl -MCPAN -e 'install Catalyst::Devel'
で終了のようです。実際、Cygwinで環境下でそれを実行すると、OKでした。
ディレクトリー構成
前章のようにインストールが終了し、例えば、TRSというようなモジュールを作成すると
# catalyst.pl TRS # cd TRS # script/trs_create.pl view TT TT
を打ち込んで出来たのが、
TRS
│ Changes
│ Makefile.PL
│ README
│ trs.yml
│
├─lib
│ │ trs.pm
│ │
│ └─trs
│ ├─Controller
│ │ Root.pm
│ │
│ ├─Model
│ └─View
│ TT.pm
│
├─root
│ │ favicon.ico
│ │ static_test.tt2
│ │
│ └─static
│ └─images
│ btn_120x50_built.png
│ btn_120x50_built_shadow.png
│ btn_120x50_powered.png
│ btn_120x50_powered_shadow.png
│ btn_88x31_built.png
│ btn_88x31_built_shadow.png
│ btn_88x31_powered.png
│ btn_88x31_powered_shadow.png
│ catalyst_logo.png
│
├─script
│ trs_cgi.pl
│ trs_create.pl
│ trs_fastcgi.pl
│ trs_server.pl
│ trs_test.pl
│
└─t
01app.t
02pod.t
03podcoverage.t
view_TT.t
ディレクトリーを1つ1つ見ていくと、
-
TRSルート
-
Changes
これは基本的には必要なし。
-
Makefile.PL
通常のモジュールのMakefile.PLじゃなさそうなんですが、現状何をやるものがわからない(いずれ調査)。なくても、もちろん大丈夫。
-
README
これは基本的には必要なし。
-
trs.yml
これは設定ファイルなので、必要。
-
-
libディレクトリー
プログラム自体はこのディレクトリー以下に配置する。
-
Controller
MVCのCを置くところ。
-
View
MVCのVを置くところだが、現実にはTT.pmだけかも。
-
Model
MVCのMを置くところ。
-
-
rootディレクトリー
テンプレートや画像ファイルなどの静的ファイルをここに格納。
-
scriptディレクトリー
ユーティリティーコマンド(ひな形などを作成したりするもの)やCGIモードで使うもの、テスト用のPerlで実装されたサーバーなどのスクリプト群。
-
tディレクトリー
テストディレクトリー。
デフォルトではない方法をとるならば
基本的に、上記の設定でもOKならば良いのですが、実際にはrootディレクトリーのような静的ファイルをもう少し細かく分けたりするにはStatic::SimpleというCatalystのpluginの設定を変更すると良いでしょう(ここを参照)。
また、Template Tool Kitの設定等は、TT.pmというViewクラスで指定することになります。
use base 'Catalyst::View::TT';
__PACKAGE__->config({
CATALYST_VAR => 'Catalyst',
INCLUDE_PATH => [
TRS->path_to( 'root', 'src' ),
TRS->path_to( 'root', 'lib' ),
],
PRE_PROCESS => 'config/main',
WRAPPER => 'site/wrapper',
ERROR => 'error.tt2',
TIMER => 0,
TEMPLATE_EXTENSION => '.tt2',
EVAL_PERL => 1,
});
上記の設定ですと、
-
CATALYST_VAR
は、テンプレート内で、カタリストオブジェクトを何で参照するかという指定。
-
INCLUDE_PATH
テンプレートファイルの検索パスをroot/srcとroot/libにする。
-
PRE_PROCESS
実際パースするテンプレートの前に、先にパースするテンプレートはconfig/mainというファイルにする。
-
WRAPPER
wrapperファイルはsite/wrapperファイルにする。
-
ERROR
エラーがあったら、error.tt2とする。
-
TIMER
ここにちょっとだけ書いてあるけれど、ちょっと保留。
-
TEMPLATE_EXTENSION
拡張委はtt2とし(なかったら?)
-
EVAL_PERL
NativeなPerlのコードを書けるようにする。
というように設定しています。ディレクトリに関してはINCLUDE_PATHでしていますね。その他はほとんどがTemplate Tool Kitの機能の設定なので、詳しく知りたければ、ここに書いてあるので、ここで詳細に研究しましょう。
とここまで書いて、もともとこのような設定をデフォルトで行うコマンドがあるようです。
# script/trs_create.pl view TT TTSite
####
とやると、どうやら幸せになれそうです。
CGIモードで実行させるには
<URL:http://d.hatena.ne.jp/pekeq/20060407/p1>を参考に、次のようにするとデフォルトの画面は表示が出来ました。
- Cygwinの/home/chikkun/perl で、 catalyst.pl trs を実行させ(もちろんbash上で)、まずはtrsのひな形を作成。
- /etc/apache/httpd.conf の中を編集。
- <Directory "/home/httpd/html"> に ExecCGI を追加。
- AddHandler cgi-script .cgi .pl を設定。
-
さらに(ここが要ですが)、httpd.confに次を加える。
<Directory "/home/chikkun/perl/trs/script/"> Options +ExecCGI <Files trs_cgi.pl> SetHandler cgi-script </Files> </Directory> ScriptAlias /trs/ /home/chikkun/perl/trs/script/trs_cgi.pl/そこで、apacheをリスタートしてから、http://localhost/trs/とブラウザーで打ち込めば、Catalystのデフォルト画面が見ることができました(よかった、よかった)。
Catalyst Plugins 探訪
Catalyst::Plugin::Charsets::Japanese
これは、文字列の変更などを自動で行ってくれるとっても助かるプラグイン。けれどもその変更対象がどの辺まであるのかわからないので、少々調査。
finalize
Pluginはhttp://search.cpan.org/~sri/Catalyst-5.55/lib/Catalyst/Manual/WritingPlugins.podによれば、finalizeとpreparationとdispatchを定義しろ、と書いてあるので、その辺から調べてみると・・・
1:
2:
3: sub finalize {
4: my $c = shift;
5: unless ( $c->response->body and not ref $c->response->body ) {
6: return $c->NEXT::finalize;
7: }
8: unless ( $c->response->content_type =~ /^text|xml$|javascript$/ ) {
9: return $c->NEXT::finalize;
10: }
11:
12: my $content_type = $c->response->content_type;
13: $content_type =~ s/\;\s*$//;
14: $content_type =~ s/\;*\s*charset\s*\=.*$//i;
15: $content_type .= sprintf("; charset=%s", $c->charsets->out->name );
16: $c->response->content_type($content_type);
17:
18: my $body = $c->response->body;
19:
20: if( $c->charsets->in->name eq 'UTF-8' && utf8::is_utf8($body) ) {
21: utf8::encode($body);
22: }
23:
24: my $in = $c->charsets->in->abbreviation;
25: my $out = $c->charsets->out->method;
26: $body = Jcode->new($body, $in)->$out;
27:
28: $c->response->body($body);
29:
30: $c->NEXT::finalize;
31: }
32:
33:
- 最初はCatalyst本体で呼ばれる、NEXT::finalizeで自分自身も呼ばれるのだろうが、必要がなければ、次のプラグインのfinalize呼び出すのが、10行目あたりまで。
- responseからcontent_typeをもらって(たぶん、「Content-type: text/html;charset=Shift_JIS」みたいなのを想定?)、末尾の;とスペースを削除し、charset=Shift_JISも削除し、outで指定しているものに書き換えているのが、16行目あたりまで。
- inがutf8で、かつ、実際bodyがutf8だったら、フラグを剥がす。そして、Jcodeでbodyをエンコードして、次へ進む、というのが最後までの内容。
setup
1:
2:
3: sub setup {
4: my $self = shift;
5: $self->NEXT::setup(@_);
6: my $setting = $self->config->{charsets} || 'UTF-8' ;
7: if(ref $setting eq 'HASH') {
8: $self->charsets->set_inner($setting->{in});
9: $self->charsets->set_outer($setting->{out})
10: } else {
11: $self->charsets->set_inner($setting);
12: $self->charsets->set_outer($setting);
13: }
14: if($self->debug){
15: $self->log->debug($self->charsets->in->name." is selected for inner code.");
16: $self->log->debug($self->charsets->out->name." is selected for outer code.");
17: }
18: }
19:
- ymlの設定ファイルにcharsetsが書いてあれば、それを $self->config->{charsets} に代入し、そうでなければ、デフォルトでutf8を代入。
-
前項で代入された$self->config->{charsets}に入っているのが、HASHのリファレンスだったら、たぶん
MyApp->config->{charsets} = { in => 'EUC-JP', out => 'Shift_JIS', };というように定義してあったりすると、inとout毎に、$self->charsets->set_inner($setting->{in});のようにセットしている。そうでなければ(つまりHASHのリファレンスでなければ)、同じものを両方セットする。
ちなみにファイルの最初の頃に
__PACKAGE__->charsets( Catalyst::Plugin::Charsets::Japanese::Handler->new \ );と、charsetsには文字コードそのものを登録するのじゃなく、ハンドラーを登録しているので、そのハンドラー(後述)のメソッドを使っているよう。
prepare_parameters
1:
2:
3: sub prepare_parameters {
4: my $c = shift;
5: $c->NEXT::prepare_parameters;
6:
7: my $in = $c->charsets->in->method;
8: my $out = $c->charsets->out->abbreviation;
9:
10: for my $value ( values %{ $c->request->{parameters} } ) {
11: if( ref $value && ref $value ne 'ARRAY' ) {
12: next;
13: }
14: for ( ref($value) ? @{$value} : $value ) {
15: $_ = Jcode->new($_, $out)->h2z->$in;
16: utf8::decode($_) if $c->charsets->in->name eq 'UTF-8';
17: }
18: }
19: }
20:
21:
これは、たぶん、Catalystがやっているメソッドをoverrideすのじゃなく、pluginに登録されいるものを、順繰りにそのメソッド(ここではprepare_parameters)を実行するのであり、このprepare_parametersはrequestに入っているデータを処理するもののよう。ちなみに、 [<source></source> is illegal in <p>] とうようなメソッドをCatalystは実行している模様。
- Jcodeのメソッドは通常、 $sjis = $j->sjis のようにアロー演算子の後のメソッド名(その文字コードにする)や、newの第1引数には文字列そのものだが、第2引数には元々の文字コードを入れるので、それらを $in,$out に代入している。
-
次に、$c->request->{parameters}にはHASHのリファレンスが入っているようなので、それをデリファレンスして、それらの値ごとにforを回しつつ、もしその値がリファレンスでかつ配列のリファレンスでないときには、何もしないでループさせ、次にもしその値がリファレンスじゃなく、ただのスカラーだったら、それを文字コード変換し、もし配列だったらそれごとにループさせ、それぞれの値を文字コード変換する。outがutf8だったら、フラグを立てる。
リファレンスなので、もともとの$c->request->{parameters}に入っている値はしっかり変更しているわけね。それから、最後のfor文の書き方はもらっちゃおう。
基本的には、ここでHTMLのフォームから入ってきたデータをoutからinの文字コードに変換しているようですが、ちょいと気になるのは$_ = Jcode->new($_, $out)->h2z->$in;で、半角から全角に変更しているところ(半角カタカナを利用しない場合が普通だからいいっか)。
その他
他にクラスが3つ定義されているが、関係として、Catalyst::Plugin::Charsets::Japaneseクラスの中の、charsetsというインスタンス変数にCatalyst::Plugin::Charsets::Japanese::Handlerが入っており、このCatalyst::Plugin::Charsets::Japanese::Handlerのインスタンス変数のinとoutにCatalyst::Plugin::Charsets::Japanese::Charsetがそれぞれ入っている。このクラスにはname abbreviation methodの3つのインスタンス変数があり、ここに文字コードを表す文字列が入っている(Jcodeのメソッド名も同様)。
で、Catalyst::Plugin::Charsets::Japanese::Charsetをnewする際に、文字コードをContent-TypeのCharsetsに使うものと、Jcode使うものに分けている。
結論
こう見てくると、このプラグインで行っていることは(utf8のフラグをとったり、付けたりを除けば)、次の2つだけ。
- Content-TypeのCharsetsをoutの文字コードにする。
- リクエストのパラメータに入っている、文字列をoutからinに変換する。
Catalyst::Plugin::Static::Simple
以前から使っていたけれど、よくわかっていなかったのでちょっとメモ。
デフォルトでは
- tmpl
- tt
- tt2
- html
- xhtml
の拡張子はカタリストを通してパースされる。つまり、静的なStatic::Simpleとは無関係。したがって、例えば、htmlを静的な単なるファイルとして扱いたい場合は、設定を変える必要がある。逆に言えば、それ以外の拡張子のものは静的なファイルとして扱われることになる。
設定
loggingを有効にする
デフォルトでは静的なファイルのリクエストは無効になっているので、有効にしたかったら、
MyApp->config->{static}->{no_logs} = 0;
とする。
ディレクトリーを静的モードにする
rootディレクトリー以下のトップレベルのディレクトリーを定義するには
MyApp->config->{static}->{dirs} = [
'static',
qr/^(images|css)/,
];
root意外にも検索パスを追加するには
MyApp->config->{static}->{include_path} = [
'/path/to/overlay',
\&incpath_generator,
MyApp->config->{root}
];
などとしておくと(サブルーチンのリファレンスもOKなんですね---でもあまり必要そうじゃないので、とりあえず無視しておこう)、
/images/logo.jpg
は、
/path/to/overlay/images/logo.jpg
/dynamic/path/images/logo.jpg
/your/app/home/root/images/logo.jpg
という順番に検索していき、見つかった最初のものを返すらしい。
[2007-04-28 15:22]
by chikkun


