PerlでAtomPubサーバを作ろう!

第1回 もっとも簡単なAtomPubサーバを作ってみる

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

モデルとテーブルの作成

Catalyst::Controller::Atompubでは,好きな種類のモデルを使うことができます。ここでは,Catalyst::Model::DBICを利用します。DBICは,Perlでよく使われるO/Rマッパーです。

テーブル作成

まず,エントリを格納するテーブルを作成します。データベースにはSQLiteを使うことにします。データベース名をtest.dbとし,次のようなテーブルを作成します。

MyBlog % sqlite3 test.db
sqlite> CREATE TABLE entries (
   ...>   id     INTEGER PRIMARY KEY,
   ...>   edited INTEGER,
   ...>   uri    TEXT UNIQUE,
   ...>   xml    BLOB
   ...> );

idはエントリの通し番号です。editedはエントリの最終更新日時です。UNIX time(1970年からの秒数)に変換してから格納するため,整数型(INT)にしています。uriはエントリのURIです。xmlには,XMLを文字列として格納します。

モデルの作成

次に,モデルを実装します。ヘルパスクリプトを使ってひな形を作成します。

MyBlog % perl script/myblog_create.pl model DBIC DBIC::Schema MyBlog::Model::Schema dbi:SQLite:dbname=test.db

コマンドの引数は次の通りです。

モデル作成スクリプトの引数

引数説明
model作成対象(MVCのいずれか)
DBIC作成するクラス名(フルパスは MyBlog::Model::DBIC)
DBIC::Schemaスーパークラス名(フルパスはCatalyst::Model::DBIC::Schema)
MyBlog::Model::Schemaスキーマ情報を扱うクラス名
dbi:SQLite:dbname=test.dbデータベースへの接続情報

コマンドを実行すると,lib/MyBlog/Model/DBIC.pmが作成されます。

続いて,データベースのスキーマ情報(テーブルの構成)を扱うMyBlog::Model::Schemaモジュールを作成します。DBIx::Class::Schema::Loaderをサブクラス化すると,スキーマ情報をデータベースから自動的に取得できるので,そのようにしておきます。

lib/MyBlog/Model/Schema.pm

package MyBlog::Model::Schema;
use base qw(DBIx::Class::Schema::Loader);
1;

コレクションコントローラの作成

コレクションを実装するコントローラを作成し,リソース操作(List+CRUD)を実装します。

ヘルパスクリプトを使ってコントローラのひな形を作成します。

MyBlog % ./script/myblog_create.pl controller EntryCollection Atompub::Collection

コマンドの引数は次の通りです。

コントローラ作成スクリプトの引数

引数説明
controller作成対象(MVCのいずれか)
EntryCollection作成するクラス名(フルパスはMyBlog::Controller::Collection)
Atompub::Collection スーパークラス名(フルパスはCatalyst::Controller::Atompub::Collection)

コマンドを実行すると,lib/MyBlog/Controller/EntryCollection.pmが作成されます。ファイルにはリソース操作のスケルトンが記述されていますので,順に埋めていきます。

Catalyst::Controller::Atompubでは,リソースを操作するメソッドに"Atompub"という属性を付与し,属性の引数で操作の種類を表します。たとえば,リソースの列挙(List)を実装するメソッドには,次のように":Atompub(list)"という属性を付けます。なお,メソッド名はなんでもかまいません。

メソッド属性

sub get_feed :Atompub(list) {
    # メンバを列挙する...
}

それでは,5つの操作を実装します。数が多いですが,ひとつひとつは難しくありません。

メンバの列挙 (List)

メンバの列挙(lib/MyBlog/Controller/EntryCollection.pm)

sub get_feed :Atompub(list) {
    my($self, $c) = @_;

    # フィード (XML::Atom::Feed) のひな型
    my $feed = $self->collection_resource->body;

    # entriesテーブルからエントリを取得する (更新日時の新しい順)
    my $rs = $c->model('DBIC::Entries')
               ->search({}, { order_by => 'edited DESC' });

    # フィードのひな形にエントリを追加する
    while (my $entry_resource = $rs->next) {
        my $entry = XML::Atom::Entry->new(\$entry_resource->xml);
        $feed->add_entry($entry);
    }

    # 成功したらtrueを返す
    return 1;
}

このメソッドが呼ばれる前に,スーパークラス(Catalyst::Controller::Atompub::Collection)はフィードのひな形を作成します。ひな形にはidやlink,titleが設定します。

このメソッドでは,ひな形を受け取り,エントリを追加します。AtomPubの枝葉末節はスーパークラスが処理するので,プログラマはリソースの操作(この場合はエントリの追加)のみを実装します。

著者プロフィール

井上武(いのうえたける)

NTTに入社後,未来ねっと研究所でマルチキャストやモバイルIPなどのネットワーク技術の研究開発に取り組んでいたが,最近はWebアーキテクチャに関する仕事をしている。

URLhttp://teahut.sakura.ne.jp/