xaicron Yokohama.pm #7 (2011-05-13)
miyagawa さんが使えるようになりました
$ easy_install dotcloud $ dotcloud create nekokak $ dotcloud deploy --type perl nekokak.www
とかやるといろいろあって、おもちゃ箱ができる。
かんたんですね。
詳しくはログイン後のチートシートを読んでね♡
とりあえず簡単なので NoPaste 的なアプリを動かしてみる
use strict;
use warnings;
use Plack::Request;
use Plack::Response;
use Text::Xslate;
use DBIx::Connector;
use Router::Simple;
use Encode qw(decode_utf8 encode_utf8);
my $router = Router::Simple->new;
$router->connect('/', {action => 'index'});
$router->connect('/create', {action => 'create'}, {method => 'POST'});
$router->connect('/{id:[1-9]\d*}', {action => 'content'});
my $conn = DBIx::Connector->new('dbi:SQLite:nopaste.db', '', '', {
RaiseError => 1,
AutoCommit => 1,
PrintWarn => 0,
PrintError => 0,
sqlite_unicode => 1,
}) or die $DBI::errstr;
my $xslate = Text::Xslate->new(
path => ['tmpl'],
syntax => 'TTerse',
);
sub {
my ($found) = $conn->run(sub {
shift->selectrow_array(
'SELECT COUNT(tbl_name) FROM sqlite_master WHERE tbl_name = ?',
undef,
'paste',
);
});
return if $found;
$conn->txn(sub {
my $dbh = shift;
$dbh->do(<< 'SQL');
CREATE TABLE paste (
id INTEGER PRIMARY KEY,
title TEXT,
content TEXT NOT NULL,
created_on INTEGER
)
SQL
$dbh->commit;
});
}->();
sub render {
my ($file, $args) = @_;
my $html = encode_utf8 $xslate->render($file, $args);
return [200, [
'Content-Type' => 'text/html; chatset=utf8',
'Content-Length' => length($html),
], [$html]];
}
sub make_permalink {
my ($req, $id) = @_;
my $uri = $req->base;
$uri->path($id);
$uri->as_string;
}
sub {
my $env = shift;
my $req = Plack::Request->new($env);
if (my $p = $router->match($env)) {
if ($p->{action} eq 'index') {
return render('index.xt');
}
elsif ($p->{action} eq 'content') {
my $id = $p->{id};
my $row = $conn->run(sub {
my $dbh = shift;
$dbh->selectrow_hashref(
'SELECT * FROM paste WHERE id = ?',
undef,
$id,
);
});
return [404, [], ['Not Found']] unless $row;
return render('content.xt', {
%$row,
link => make_permalink($req, $id),
});
}
elsif ($p->{action} eq 'create') {
my $title = decode_utf8 $req->param('title');
my $content = decode_utf8 $req->param('content');
unless (length $content) {
return [400, [], ['Bad Request']];
}
my ($id) = $conn->txn(sub {
my $dbh = shift;
$dbh->do(
'INSERT INTO paste(title, content, created_on) VALUES(?, ?, ?)',
undef,
($title, $content, time),
);
$dbh->commit;
$dbh->sqlite_last_insert_rowid;
});
return render('content.xt', {
title => $title,
content => $content,
id => $id,
link => make_permalink($req, $id),
});
}
}
else {
return [404, [], ['Not Found']];
}
};
簡単ですね。
.
├── Changes
├── MANIFEST.SKIP
├── META.yml
├── Makefile
├── Makefile.PL
├── README
├── app.psgi
├── inc
│ └── Module
│ ├── Install
│ │ ├── AuthorTests.pm
│ │ ├── Base.pm
│ │ ├── Can.pm
│ │ ├── Fetch.pm
│ │ ├── Makefile.pm
│ │ ├── Metadata.pm
│ │ ├── Repository.pm
│ │ ├── Win32.pm
│ │ └── WriteAll.pm
│ └── Install.pm
├── lib
│ └── nopaste.pm
├── t
│ └── 00_compile.t
├── tmpl
│ ├── content.xt
│ └── index.xt
└── xt
├── 01_podspell.t
├── 02_pod.t
├── 03_pod-coverage.t
├── 04_perlcritic.t
├── 05_script-shebang.t
└── perlcriticrc
さっきのような構成を *全部* git に commit
$ dotcloud push xaicron.paste {path}
とかやると魔法が起きてアプリがうごく!!!
依存モジュールは Makefile.PL に書いとくとよしなにしてくれる。超らくちん。
use inc::Module::Install;
name 'nopaste';
all_from 'lib/nopaste.pm';
requires 'Plack';
requires 'DBD::SQLite';
requires 'DBIx::Connector';
requires 'Text::Xslate';
requires 'Encode';
requires 'Router::Simple';
test_requires 'Test::More', 0.98;
tests join q{ }, map { sprintf 't%s.t', '/*' x $_ } 1..3;
author_tests 'xt';
WriteAll;
注意点としては Module::Install 使ってる場合は inc も commit すること。
$ git add -f inc $ git commit -m 'added inc'
忘れるとよよよ。
とっても簡単に PSGI アプリを動かせて便利ですね!
みんなも使いましょう!
ご清聴ありがとうございました。