Mojoを使って自作ウェブアプリをよりポータブルに!

第3回 サンプルフレームワーク:Mojolicious

この記事を読むのに必要な時間:およそ 5 分

2009年12月8日:サンプルコードを現在のバージョンで動作するよう修正しました。

Mojoliciousを使ってみよう

前回はすでにできあがったアプリケーションにMojoを組み込んで移植性を高める方法を見ました。今回はこれから新しいアプリケーションを構築する際のベタープラクティスのひとつとして,Mojoのパッケージに同梱されているMojoliciousというフレームワークを利用する方法を紹介します。

まずはひな形から

Mojoliciousのアプリケーションも,Mojoの場合と同じくまずはひな形をつくるところから始めます。今回は簡単なWikiもどきをつくってみましょう。例によってMojoをインストールしたディレクトリでこのようなコマンドを入力します。

> perl script/mojolicious generate app SimpleWiki
> cd simple_wiki

Mojoのひな形に比べていくらか余分にファイルが生成されます。開発用サーバの立ち上げ方はMojoアプリの場合と同じですので,初期画面を見たい方は各自ご確認ください。

lib/SimpleWiki.pmはこのようになっています。

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というメソッドのなかにアプリケーションを入れましたが,Mojoliciousの場合,内部に隠蔽されているhandlerではなく,サーバ起動時に1回だけ実行されるstartupと,リクエストがあるたびに実行されるdispatchというメソッドを上書きしていきます。

dispatchメソッドのほうは,まずpublicディレクトリ以下の静的ファイルをチェックし,それがなければURLに応じたコントローラに処理を渡し,それでもだめならあらかじめ用意されている静的な404ファイルを返すようになっています。

startupメソッドでは必要に応じて独自のコンテキストを用意したり,例にはあがっていませんがデータベースなどの設定を行うのが一般的ですが,このパス(ルート)を解析する部分にはあまりなじみがないかもしれません。

Merbライクなディスパッチャ

Mojoのルータ(ディスパッチャ)は,最近Ruby on Railsが採用したことで話題になっているMerbのルータによく似たものです。基本的にはURLのパス部分から(あるいはそれとは独立して)コントローラ名とそのコントローラ内で実行するメソッド(アクション)名,必要に応じて任意のキャプチャを取得するためのルールをroute内に記述し,toにはデフォルト値を記述する(デフォルト値が用意されている項目は省略可能になる)⁠と考えておけばよいでしょう。

生成されたひな形の例で言うと,http://127.0.0.1:3000/wiki/create/10にアクセスすれば,lib/SimpleWiki/Wiki.pmというコントローラのcreateというメソッドが呼ばれ,http://127.0.0.1:3000/にアクセスすると,デフォルトで指定されているlib/SimpleWiki/Example.pmというコントローラのwelcomeというメソッドが呼ばれる,という寸法です(キャプチャしたcontroller,action,idの値はコンテキストオブジェクト内部のstashというハッシュに格納されます)⁠

今回はWikiもどきをつくりたいので,まずはルータの設定を多少変更しましょう。コントローラは固定で,CRUDのメソッドはなるべく省略しやすいよう後ろに回します。

@@ -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のデータを扱うモデルをつくります。ここではデータベースは使わず,単純なファイルの入出力ですませてしまいます。エディタでこのようなlib/SimpleWiki/Model.pmを用意してください(以下,スペースの都合でupdateとdeleteに関する部分は省略しますが,余力のある方はぜひご自分で実装してみてください)⁠

package SimpleWiki::Model;

use strict;
use warnings;
use File::Spec::Functions 'catfile';
use base 'Mojo::Base';

__PACKAGE__->attr(datadir => 'data');

sub datafile {
    my ($self, $id) = @_;
    return catfile($self->datadir, $id);
}

sub create {
    my ($self, $id, $data) = @_;
    open my $fh, '>', $self->datafile($id) or return;
    print $fh $data;
    return 1;
}

sub read {
    my ($self, $id) = @_;
    open my $fh, '<', $self->datafile($id) or return;
    return do { local $/; <$fh>; };
}

1;

著者プロフィール

石垣憲一(いしがきけんいち)

あるときは翻訳家。あるときはPerlプログラマ。先日『カクテルホントのうんちく話』(柴田書店)を上梓。最新刊は『ガリア戦記』(平凡社ライブラリー)。

URLhttp://d.hatena.ne.jp/charsbar/