ついに出た!最新Perlフレームワーク「Ark」徹底解剖

第4回Ark チュートリアル:応用編(その2)

前回に引き続き、サンプルアプリケーションとしては掲示板を開発しながら、Arkの利用方法について紹介します。

掲示板の概要

今回作成するアプリケーションは、OpenID認証を使用したシンプルな掲示板アプリケーションです。

ここまでのおさらい

前回依存モジュールの準備、モデルの作成、テンプレートの利用など、基礎部分の開発を行いました。今回は、その続きを行っていきます。

アプリケーションの作成(続き)

ログイン処理

次にログイン処理を作っていきましょう。今回はOpenIDを使用したログイン処理を実装します。

Arkではログイン処理などはプラグインとして用意されています。今回は認証プラグインとセッションプラグインを使用してログイン処理を作成します。

プラグインを使うにはアプリケーションクラス(MiniBBS.pm)でその使用を宣言します。具体的には以下のようにします。

use_plugins qw{
    Session
    Session::State::Cookie
    Session::Store::Memory

    Authentication
    Authentication::Credential::OpenID
    Authentication::Store::Null
};

これでセッションと認証のプラグインをロードできます。ロードしたプラグインを見てみましょう。

まずセッションプラグインは、セッションIDを保存するためのStateと、セッションデータを保存するためのStoreの組み合わせを指定する必要があります。今回のコードでは

Sessionセッションプラグイン
Session::State::CookiecookieにセッションIDを登録する
Session::Store::Memoryメモリにセッションデータを持つ

を使用します。たとえば、Cookieの代わりにURLにセッションIDを埋め込みたいときはState::Cookieの代わりにState::URIを使用したり、データをmemcachedなどに保存したり、その他Cacheインターフェースを使用してデータを保存したい場合はStore::Modelを使用したりということができます。

認証プラグインもセッションと同様に、認証方法を指定するCredentialとユーザ情報を保存するStoreというプラグインを組み合わせて使用します。

今回はOpenID認証を使用しているため、ユーザ情報は外部のサービスが持っていますのでCredentialのみの指定で使用します。そのような場合はStore::Nullというプラグインを使用します。

もちろん、OpenID認証を使用していてもユーザ情報をアプリケーションで拡張するために自前のStoreと組み合わせることも可能です。ですが、今回はOpenID認証でログイン処理を使うだけなので省略します。

プラグインの準備ができましたので、次はログイン・ログアウトを処理するコントローラを書きます。Loginというコントローラ名にしましょう。

$ ark.pl controller Login

というコマンドでひな形を生成します。

URL的には/loginでログイン、/logoutでログアウトとなるようにコントローラを書くと以下のようになります。

sub login :Path :Args(0) {
    my ($self, $c) = @_;

    if (my $user = $c->authenticate) {
       # login 成功
       $c->redirect( $c->uri_for('/') );
    }
}

sub logout :Global {
    my ($self, $c) = @_;
    $c->logout;
    $c->redirect( $c->uri_for('/') );
}

また、ログインフォームのテンプレートをroot/login/login.mtとして置いておきます。

<p>OpenID でログイン</p>

<form method="get">
<p>
  <label for="openid_identifier">OpenID URI:</label>
  <input type="text" id="openid_identifier" name="openid_identifier" />
</p>
<p><input type="submit" value="login"/></p>
</form>

これでログイン処理は完成です。

モデルを使用する

最後に、BBSモデルを使用し掲示板機能を付けたら完成です。投稿画面とメッセージ一覧が同じページにあるようなシンプルな掲示板を考えてみます。

まずテンプレート(root/index.mt)はこのようにします。

? if ($c->user) {

<form method="post">
  <p>
    <label for="message">メッセージ:</label>
    <textarea id="message" name="message"></textarea>
  </p>
  <p><input type="submit" value="投稿"/></p>
</form>

? } else {

<p>メッセージを投稿するには<a href="<?= $c->uri_for('/login') ?>">ログイン</a>が必要です。</p>

? }


? while (my $msg = $s->{messages}->next) {

<hr />

<dl>
  <dt>ID:</dt>
  <dd><?= $msg->user ?></dd>
  <dt>Date:</dt>
  <dd><?= $msg->created_date ?></dd>
  <dt>Body:</dt>
  <dd><?= $msg->body ?></dd>
</dl>

? }

上から順番に見てみましょう。

? if ($c->user) {

でログイン済みのときはメッセージ投稿フォームを表示させています。そして、それに対応する、

? } else {

の部分では、ログインしてないときのログイン画面へのリンクを表示するようにしています。

そして最後に

? while (my $msg = $s->{messages}->next) {

でメッセージ一覧を表示させています。この$s->{messages}はどこから来たのでしょう。これはコントローラで書いてあげる必要があります。Rootコントローラのindexアクションをこのように書き換えます。

sub index :Path :Args(0) {
    my ($self, $c) = @_;
    $c->stash->{messages} = $c->model('BBS')->messages;
}

最初に設定したモデルからメッセージ一覧を$c->stashに格納しています。テンプレート内ではこのstashは$sでアクセスできるようになっていますので、$s->{messages}で値をとることができます。

最後に投稿機能を書いていきましょう。indexアクションをさらに以下のように編集します。

sub index :Path :Args(0) {
    my ($self, $c) = @_;

    if ($c->req->method eq 'POST') {
        $c->detach('post');
    }

    $c->stash->{messages} = $c->model('BBS')->messages;
}

リクエストメソッドがPOSTだった場合(メッセージが投稿された場合⁠⁠、postアクションに処理を飛ばすという意味です。そしてその飛ばし先のpostアクションは以下のように書きます。

sub post :Private {
    my ($self, $c) = @_;

    if ($c->user and my $msg = $c->req->param('message')) {
        $c->model('BBS')->add_message({
            user => $c->user->obj->{display},
            body => $msg,
        });
    }

    $c->redirect( $c->uri_for('/') )
}

ユーザがログイン済みでかつ、メッセージパラメータがある場合、BBSモデルを使用しデータを更新します。そしてそのあと、トップにリダイレクトし更新されたデータを表示する。というような処理となっています。

動作確認

以上で、シンプルな掲示板アプリケーションが完成しました。さっそく動作の確認をしてみましょう。

$ ark.pl server -d

として開発サーバを立ち上げてみてください。そしてhttp://localhost:4423/にアクセスします。ログインが必要です、というメッセージが表示されていますか? 表示されていればとりあえずうまく動いています。

ログインページに飛んで、適当な OpenIDアカウントを入力してみてください。現在のバージョンのNet::OpenID::Consumerが入っていれば、このアプリケーションはOpenID 2.0に対応しており、⁠mixi.jp」「yahoo.co.jp」など、OpenID 2.0対応のプロバイダであればドメインを入力するだけでログインすることができます。

ログインの成功、そのあとの掲示板への書き込み、などがすべてうまく動いたら成功です!

今回のまとめ

今回は、シンプルな掲示板の作成を通してArkアプリケーションの書き方を説明しました。

Arkアプリケーションはどのような構造になっているか、どのようにモジュールを分けるのか、などのだいたいのイメージはつかめましたか?

ここからさらに先に進みたい方は、オンラインドキュメントや、Catalyst関係の記事などを参考にもっと複雑なアプリケーションを作ってみてください。

また、先ほども紹介した『モダンPerl入門』のCatalystの項は現在のCatalystアプリケーションの設計について一番詳しく書かれた文献となっており、非常にオススメです。Catalystアプリケーションの構成について書かれている項なのですが、それはそのままArkに当てはめることが可能です。

Arkの今後

Arkは現状バージョン0.1のリリース候補版が出ている状況です。これは実装はほとんどコードフリーズしており、ドキュメントがそろい次第0.1をリリースします。

現在、日々カヤック社員によって拡張されつづけており、すでに社内ではモバイル用のプラグインも一通りそろっていたりと着々と進化しています。モバイル対応は次期バージョン(0.2)で正式に組み込む予定です。

また、Module::Setupベースのopensource.kayac.com/ja/projects/ark/documents/ark"">ark.plスクリプトは、最近Module::Setup自体が進化したためより高機能なことができるようになったため、それを取り込みたいと考えています。自前テンプレートを定義することがより柔軟にできるようになるはずです。

Arkの開発は、github上で行っています。Ark を拡張したりプラグインやコンポーネントを開発したりされた方は、ぜひgithub上でpull requestをお願いします。できるだけ本体に取り込みたいと思っています。

開発に協力してくれるかた、もしくは何か質問があるかたは、以下にIRCチャンネルを作成しましたので、そちらからコンタクトください。

  • #ark @ irc.perl.org

それでは、短い連載でしたがご精読ありがとうございました!

おすすめ記事

記事・ニュース一覧