Amon2を使ったアプリ開発
前回は amon2 を触ってみましたが ( Amon2 (PSGI フレームワーク) - keisyuのブログ ) これで少しアプリっぽいものを作って勉強してみようと思います。作るものは掲示板みたいなものを作って見ようと思います。
まずは amon2-setup.pl で flavor はBasicでスタートすることにします。
$ amon2-setup.pl --flavor=Basic SimpleBBS $ carton install
今回はplackupを使って起動して開発することにします。-R オプションに監視ディレクトリを指定して起動するとコードの変更時にサーバを停止することなく自動でリロードされるようで便利のようです。
$ carton exec -- plackup -R ./lib -Ilib script/simplebbs-server
さて作るもの(方針)はこんな感じにします
- 超簡易な掲示板
- DBはMySQLを使う
- flavor:BasicでバンドルされているORM(Teng)は使わずにdbhで操作する
- Templeteのsyntaxは TT2 compatible が慣れているのでそれを使う( ひな形のは捨てる )。
- その他開発に便利そうなやつは勉強がてら触ってみる。
DB(TABLE)の定義
投稿が保存される単一テーブルにします sql/mysql.sql を以下にします
CREATE TABLE IF NOT EXISTS entries ( id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT, body VARCHAR(255), created_at TIMESTAMP ) CHARSET=utf8;
MySQLにDatabaseを定義してテーブルを作成します
$ sudo mysqladmin create SimpleBBS
$ cat sql/mysql.sql | mysql -u root SimpleBBS
dbh (MySQL) を使う準備
cpanfile に以下を追記します
requires 'Amon2::Plugin::DBI'; requires 'DBD::mysql';
そしてインストールします
$ carton install
config/development.pl はデフォルトでsqliteに接続するひな形になっているのでこれを以下に変更します
+{ 'DBI' => [ "dbi:mysql:dbname=SimpleBBS", 'root', '', +{ mysql_enable_utf8 => 1, } ], };
開発
とりあえず、テンプレートを触るのはもうちょっと後にして、DBに直接エントリーを数個入れてそれがちゃんと取り出せるか確認してみます。
mysql> insert into entries (body) values ('Hello!'),('Amon2'),('World!!'); mysql> select * from entries; +----+---------+---------------------+ | id | body | created_at | +----+---------+---------------------+ | 1 | Hello! | 2014-02-16 18:25:58 | | 2 | Amon2 | 2014-02-16 18:25:58 | | 3 | World!! | 2014-02-16 18:25:58 | +----+---------+---------------------+
lib/SimpleBBS/Web.pm の中にこのアプリで利用するプラグインをロードする箇所があるのでそこにDBIを追加します
__PACKAGE__->load_plugins( ... 'DBI', );
lib/SimpleBBS/Web/Dispatcher.pm に各URLのエントリーポイント毎の処理を記述する箇所がありますので '/' の部分で先ほどの entries テーブルをSELECTして標準出力に表示してみることにします。
... use Data::Dumper; ... any '/' => sub { my ($c) = @_; my $entries = $c->dbh->selectall_arrayref(q[ SELECT * FROM entries ORDER BY id DESC ], { Slice => {} }); print Dumper $entries; ...
これでWebページにブラウザでアクセスするとサーバが起動しているシェルに
$VAR1 = [ { 'created_at' => '2014-02-16 18:25:58', 'body' => 'World!!', 'id' => '3' }, { 'created_at' => '2014-02-16 18:25:58', 'body' => 'Amon2', 'id' => '2' }, { 'created_at' => '2014-02-16 18:25:58', 'body' => 'Hello!', 'id' => '1' } ];
と表示されました。ちゃんとDBI経由でMySQLからデータが取得できているようです。ちょっとMVCっぽく各entryの要素をModel化します。
lib/SimpleBBS/Model/Entry.pm を以下で定義します。
package SimpleBBS::Model::Entry; use Class::Accessor::Lite ( new => 1, ro => [ qw( id body created_at )], ); 1;
これをつかて先ほどのDispacher.pmを若干修正します
... use SimpleBBS::Model::Entry; any '/' => sub { my ($c) = @_; my @entries = map { SimpleBBS::Model::Entry->new($_) } @{$c->dbh->selectall_arrayref(q[ SELECT * FROM entries ORDER BY id DESC ], { Slice => {} })}; print Dumper @entries; ....
これで出力されるログは
$VAR1 = bless( { 'created_at' => '2014-02-16 18:25:58', 'body' => 'World!!', 'id' => '3' }, 'SimpleBBS::Model::Entry' ); $VAR2 = bless( { 'body' => 'Amon2', 'created_at' => '2014-02-16 18:25:58', 'id' => '2' }, 'SimpleBBS::Model::Entry' ); $VAR3 = bless( { 'body' => 'Hello!', 'created_at' => '2014-02-16 18:25:58', 'id' => '1' }, 'SimpleBBS::Model::Entry' );
となりました。今回のサンプルではここまでModel化する必要は全く無いですがね...