Amon2 で DB を利用したウェブアプリ

SQL で DB を定義

mysql でも同様。

$ vi sql/sqlite.sql
CREATE TABLE IF NOT EXISTS member (
    id           INTEGER NOT NULL PRIMARY KEY,
    name         VARCHAR(255)
);

CREATE TABLE IF NOT EXISTS sessions (
    id           CHAR(72) PRIMARY KEY,
    session_data TEXT
);

CREATE TABLE IF NOT EXISTS entry (
    entry_id     INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    body         VARCHAR(255) NOT NULL
);

O/R マッピング

Schema.pm に Teng (O/R マッパー) 用の DB のテーブルスキーマを記載

$ vi lib/HelloAmon2/DB/Schema.pm
package HelloAmon2::DB::Schema;
use strict;
use warnings;
use utf8;

use Teng::Schema::Declare;

base_row_class 'HelloAmon2::DB::Row';

table {
    name 'member';
    pk 'id';
    columns qw(id name);
};

table {
    name 'sessions';
    pk 'id';
    columns qw(session_data);
};

table {
    name 'entry';
    pk 'entry_id';
    columns qw(body);
};

1;

DB に反映

sqlite3 db/development.db < sql/sqlite.sql

DB 操作実装

とりあえず Dispatcher に DB への操作を実装。

$ vi lib/HelloAmon2/Web/Dispatcher.pm
package HelloAmon2::Web::Dispatcher;
use strict;
use warnings;
use utf8;
use Amon2::Web::Dispatcher::Lite;

any '/' => sub {
    my ($c) = @_;
    my @entries = $c->db->search_by_sql(q{
        SELECT * FROM entry ORDER BY entry_id DESC LIMIT 10
    });
    return $c->render('index.tt' => { entries => \@entries });
};

post '/post' => sub {
    my ($c) = @_;
    if ( my $body = $c->req->param('body') ) {
        $c->db->insert(
            'entry',
            +{
                body => $body,
            }
        );
    }
    return $c->redirect('/');
};

1;

テンプレートの実装

$ vi tmpl/index.tt
<form method="post" action="[% uri_for('amon2/post') %]">
  <input type="text" name="body" />
  <input type="submit" value="Send" />
</form>

<table>
  [% FOR entry IN entries %]
  <tr>
    <td>[% entry.entry_id %]</td>
    <td>[% entry.body %]</td>
  </tr>
  [% END %]
</table>

plackup で psgi を起動

$ plackup &