2009年12月8日:サンプルコードを現在のバージョンで動作するよう修正しました。
Mojoliciousを使ってみよう
前回はすでにできあがったアプリケーションにMojoを組み込んで移植性を高める方法を見ました。今回はこれから新しいアプリケーションを構築する際のベタープラクティスのひとつとして、
まずはひな形から
Mojoliciousのアプリケーションも、
> perl script/mojolicious generate app SimpleWiki > cd simple_wiki
Mojoのひな形に比べていくらか余分にファイルが生成されます。開発用サーバの立ち上げ方はMojoアプリの場合と同じですので、
lib/
package SimpleWiki;
use strict;
use warnings;
use base 'Mojolicious';
# This method will run once at server start
sub startup {
my $self = shift;
# Routes
my $r = $self->routes;
# Default route
$r->route('/:controller/:action/:id')
->to(controller => 'example', action => 'welcome', id => 1);
}
1;
Mojoliciousアプリケーションの処理の流れ
Mojo単独で使う場合はhandlerというメソッドのなかにアプリケーションを入れましたが、
dispatchメソッドのほうは、
startupメソッドでは必要に応じて独自のコンテキストを用意したり、
Merbライクなディスパッチャ
Mojoのルータ
生成されたひな形の例で言うと、
今回はWikiもどきをつくりたいので、
@@ -13,8 +13,8 @@
my $r = $self->routes;
# Default route
- $r->route('/:controller/:action/:id')
- ->to(controller => 'example', action => 'welcome', id => 1);
+ $r->route('/:id/:action')
+ ->to(controller => 'entry', id => 1, action => 'read');
}
1;
モデルをつくる
続いてWikiのデータを扱うモデルをつくります。ここではデータベースは使わず、 モデルができたら、 $self->homeにはアプリケーションのホームディレクトリを指し示すオブジェクトが格納されています ここで、 さて、 lib/ 以前は$self->ctxに格納されていたコンテキストは、 続いて、 ここではデフォルトで生成されるtemplates/ 同様に、 これで最低限動作するようになりましたので、 lib/ Catalystをご存知の方は$self->url_ Mojoliciousを含むMojoアプリケーションにはログ機能がついています。動作確認したあとでlogディレクトリの下を見るとdevelopment. コントローラ内部からログを出力したい場合は、 最後にMojoliciousアプリケーションのテストについても触れておきましょう。 Mojoliciousアプリケーションのテストは基本的に前回見たMojoアプリケーションのテストと同じで、 さて、 次回はMojoが誕生した経緯を振り返りながら、package SimpleWiki::Model;
use strict;
use warnings;
use File::Spec::Functions 'catfile';
use base 'Mojo::Base';
__
モデルを登録する
@@ -4,6 +4,9 @@
use warnings;
use base 'Mojolicious';
+use SimpleWiki::Model;
+
+__PACKAGE__->attr(model => sub { SimpleWiki::Model->new });
# This method will run for each request
sub startup {
@@ -15,6 +18,8 @@
# Default route
$r->route('/:id/:action')
->to(controller => 'entry', id => 1, action => 'read');
+
+ $self->model->datadir($self->home->rel_dir('data'));
}
1;
コントローラをつくる
package SimpleWiki::Entry;
use strict;
use warnings;
use base 'Mojolicious::Controller';
sub create {
my $self = shift;
if (uc $self->req->method eq 'POST') {
$self->app->model->create($self->stash->{id}, $self->req->param('text'));
}
$self->render;
}
sub read {
my $self = shift;
$self->stash->{body} = $self->app->model->read($self->stash->{id});
$self->render;
}
1;
Mojoliciousのコンテキスト
テンプレートを用意する
<!doctype html>
<head><title><%= $self->stash->{id} %></title></head>
<body>
<%= $self->stash->{body} %>
</body>
</html>
<!doctype html>
<head><title><%= $self->stash->{id} %></title></head>
<body>
<form method="POST">
<textarea name="text"></textarea>
<input type="submit">
</form>
</body>
</html>
リダイレクトの扱い
@@ -8,6 +8,7 @@
my $self = shift;
if (uc $self->req->method eq 'POST') {
$self->app->model->create($self->stash->{id}, $self->req->param('text'));
+ $self->redirect_to($self->url_for(action => 'read'));
}
$self->render;
}
@@ -15,6 +16,7 @@
sub read {
my $self = shift;
$self->stash->{body} = $self->app->model->read($self->stash->{id});
+ return $self->redirect_to($self->url_for(action => 'create')) unless defined $self->stash->{body};
$self->render;
}
Mojoliciousのログ
@@ -22,4 +22,14 @@
$self->model->datadir($self->home->rel_dir('data'));
}
+sub development_mode {
+ my $self = shift;
+ $self->log->handle(*STDERR);
+}
+
+sub production_mode {
+ my $self = shift;
+ $self->log->level('error');
+}
+
1;
@@ -8,6 +8,7 @@
my $self = shift;
if (uc $self->req->method eq 'POST') {
$self->app->model->create($self->stash->{id}, $self->req->param('text'));
+ $self->app->log->info('created '.$self->stash->{id});
$self->redirect_to($self->url_for(action => 'read'));
}
$self->render;
Test::Mojoを使ったテスト
@@ -3,12 +3,17 @@
use strict;
use warnings;
-use Test::More tests => 5;
+use Test::More tests => 7;
use Test::Mojo;
use_ok('SimpleWiki');
# Test
my $t = Test::Mojo->new(app => 'SimpleWiki');
-$t->get_ok('/')->status_is(200)->content_type_is(Server => 'text/html')
- ->content_like(qr/Mojolicious Web Framework/i);
+$t->post_form_ok('/test/create' => {text => 'test is ok'})
+ ->status_is(302);
+
+$t->get_ok('/test')
+ ->status_is(200)
+ ->content_type_is('text/html')
+ ->content_like(qr/test is ok/);
Mojoliciousはあくまでサンプルにすぎません