ServersMan@VPS Catalyst のインストール


フレームワークで Python といえば Django、Ruby といえば Rails、Perl といえば Catalyst でしょう、ということで、インストールから簡易掲示板作成までやってみました。

Django、Rails、Catalyst と試してみましたが、正直、今回が一番辛かったです・・・


目次

cpan の準備

こちらで紹介してます。モジュールのインストールの手前まで終わらせてください。

インストール

cpan 経由で Catalyst をインストールするわけですが、モジュールをインストールするたびに [yes] Enterキーを求められて非常にだるいので(1,2回ならいいけど、10回以上・・・。)毎回 yes しなくてもいいようにします。※ これやっても、たまに [y] でEnterキー求められます

cpan> o conf prerequisites_policy follow
cpan> o conf commit

では、インストール。かなり時間がかかるので、お茶でも飲みましょう( ゚Д゚)⊃旦

cpan> install Catalyst::Runtime
cpan> install Catalyst::Devel
cpan> install Cataylst::View:TT
cpan> install Catalyst::Model::DBIC::Schema

雛形作成

アプリの置き場所を /var/www/catalyst/ にする場合です。

mkdir /var/www/catalyst
cd /var/www/catalyst
catalyst.pl MyApp

ファイルが自動生成されました。
開発用の簡易Webサーバを起動してみます。

cd bb
script/MyApp_server.pl

※ 以下のように引数を付けると、変更があった場合に自動でサーバが再起動されて変更内容が反映されます。かなり便利

script/MyApp_server.pl --restart

ブラウザでアクセス。

http://VPSのIPアドレス:3000/

開発用サーバを Ctrl + C で落とします。

データベースの準備

今回は SQLite を使います。

mkdir data
sqlite3 data/myapp.db
sqlite> CREATE TABLE bbs (
    id INTEGER PRIMARY KEY,
    title varchar(128) not null,
    comment text not null
);

sqlite> insert into bbs (title, comment) values('テストだよ', '(・ε・)');
sqlite> .q

data ディレクトリ内に myapp.db が出来ました。

モデルの作成

script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=static dbi:SQLite:data/myapp.db

※ 1行です

コントローラーの作成

script/myapp_create.pl controller bbs

今作ったコントローラーを見てみます。

vi lib/MyApp/Controller/bbs.pm
package MyApp::Controller::bbs;
use Moose;
use namespace::autoclean;

BEGIN {extends 'Catalyst::Controller'; }

sub index :Path :Args(0) {
    my ( $self, $c ) = @_;

    $c->response->body('Matched MyApp::Controller::bbs in bbs.');
}

__PACKAGE__->meta->make_immutable;

1;

コメントアウト除くと↑な感じです。開発用サーバを起動してブラウザで見てみます。

script/myapp_server.pl
ブラウザで http://VPSのIPアドレス:3000/bbs/

ブラウザにこんな文字が↓でてるはずです。

Matched MyApp::Controller::bbs in bbs.

コントローラーを書き換えて表示が変わるか試してみます。

vi lib/MyApp/Controller/bbs.pm
sub index :Path :Args(0) {
    my ( $self, $c ) = @_;

    $c->response->body('タイ━━━━||Φ|(|´|Д|`|)|Φ||━━━━ホ!!');
}

またブラウザでアクセスして書き換えた文字が標示されるか確認。

タイ━━━━||Φ|(|´|Д|`|)|Φ||━━━━ホ!!

ビューの作成

先程は、コントローラーを書き換えましたが、今度はビューを使ってみます。
まず、コントローラーにメソッドを追記します。場所は、index メソッドの下あたりでいいです。

vi lib/MyApp/Controller/bbs.pm
sub top :Local {
    my ( $self, $c ) = @_;

    $c->stash(yourface => '(´・ω・`)',
             template => 'bbs/top.tt');
}

ビューに使うモジュールを定義したクラスを以下のコマンドで生成します。

script/myapp_create.pl view TT TT

※ 最初の TT は、lib/MyApp/View/TT.pm のファイル名で使われます。HTML でも何でもOK
※ 2番目の TT は、ビューに Template Toolkit を指定しています。変えたいときは HTML::Template などに変更

テンプレートファイルを作成します。

mkdir root/bbs
vi root/bbs/top.tt
ビューでテンプレートを読み込んでます [% yourface %]

ブラウザでアクセス。

http://VPSのIPアドレス:3000/bbs/top

以下のように表示されていればテンプレートが使えてます。

ビューでテンプレートを読み込んでます (´・ω・`)

TIPS テンプレートのパスを変える
root 直下って何か違和感が・・・変更したい場合は、以下でできます。

vi lib/MyApp/View/TT.pm
__PACKAGE__->config(
    TEMPLATE_EXTENSION => '.tt',
    render_die => 1,
    INCLUDE_PATH => [
        MyApp->path_to( 'template' ),
    ],
);

↑の場合、アプリのディレクトリ/template が root の代わりになります。
サンプルだと、アプリのディレクトリ/template/bbs/top.tt っていう構成になります。

データベースからデータを読み込んで表示

http://VPSのIPアドレス/bbs/top に掲示板の一覧を表示してみます。

コントローラーに追記

vi lib/MyApp/Controller/bbs.pm
sub top :Local {
    my ( $self, $c ) = @_;

    $c->stash( yourface => '(´・ω・`)',
               bbs      => [$c->model('DB::Bb')->all],
               template => 'bbs/top.tt');
}

次は、ビューです。CSS部分は、どうでもいいですが、重要なのは、[% FOREACH bb IN bbs -%] のブロックです。

vi root/bbs/top.tt
ビューでテンプレートを読み込んでます [% yourface %]
<br><br>
<style type="text/css">
.bb{
    margin:5px;
}
.title {
    background-color:#0a92db;
    color:white;
    padding:5px;
}
.comment {
    margin-left:10px;
    padding:5px;
    background-color:#e2eef7;
}   
</style>

[% FOREACH bb IN bbs -%]
<div class="bb">
    <div class="title">[[% bb.id %]] <b>[% bb.title | html %]</b></div>
    <div class="comment">[% bb.comment | html %]</div>
</div>
[% END -%]

ブラウザで確認してみます。

http://VPSのIPアドレス:3000/bbs/top

1レコードしか insert してなかったので1件しか出てませんが、DBから取得→ビューで表示が実現できました。

データベースへデータを追加

次は、掲示板へ投稿できるようにしてみます。
コントローラーにメソッドを追記して、投稿データを処理するURL(/bbs/post)を作ります。場所は、topメソッドの下あたりで。

vi lib/MyApp/Controller/bbs.pm
sub post :Local {
    my ( $self, $c ) = @_;

    my $bb = $c->model('DB::Bb')->create({
        title   => $c->request->params->{title} || '無題',
        comment => $c->request->params->{comment} || '( ´∀`)<ぬるぽ',
    });

    $c->stash( yourface => '(´・ω・`)',
               bbs      => [$c->model('DB::Bb')->all],
               template => 'bbs/top.tt');
}

投稿用のフォームを作ります。別画面で作るのも面倒なので、top.tt に追加しちゃいます。

vi root/bbs/top.tt
form {
    border:2px dashed #0a92db;
    padding:10px;
    margin:10px;
}
</style>

<form method="post" action="[% c.uri_for('post') %]">
    タイトル<br><input type="text" name="title"><br>
    コメント<br><textarea name="comment"></textarea><br>
    <input type="submit" value="送信">
</form>

[% FOREACH bb IN bbs -%]
<div class="bb">
    <div class="title">[[% bb.id %]] <b>[% bb.title | html %]</b></div>
    <div class="comment">[% bb.comment | html %]</div>
</div>
[% END -%]

ブラウザで試してみます。

http://VPSのIPアドレス:3000/bbs/top

・タイトル:適当に入力
・コメント:適当に入力
・送信

投稿できました∩( ・ω・)∩

おまけ

セキュリティ関係
SQLインジェクション、XSS 的に何もしなくて大丈夫なのか

結果、こうなった

SQLインジェクションは、プレースホルダ使ってそうでさすがに大丈夫だが、XSSは超NG。
Viewは、Templete Toolkit 任せだからシラネ、ってスタンスなのかなー。
Template Toolkit 使って外部入力を出力するときは、気をつけましょう。デフォルトでエスケープしてくれればいいのに(´・ω・`)

× [% hoge %]
○ [% hoge | html %]

※ テンプレートのソースは、この問題に気づいたあと修正しました。
※ Rails、Django はちゃんとエスケープしてくれました。

参考
http://search.cpan.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial.pod

コメントを残す

メールアドレスが公開されることはありません。

Top