Row クラスにメソッドを追加B!

はじめに

昨日は、スキーマクラスに任意のメソッドをはやす Mixin の作り方を紹介しました。

今日は検索した Row クラスに対してメソッドを生やす add_method について紹介します。

Row クラスとは、 get メソッドや lookup メソッドから得られたレコードの行データが格納されている物です。

add method する

初日に Data::Model にはリレーションの機能が無いと説明しましたが、 add_method を使って簡易的なリレーションシップができます。

たとえば MyBookmark クラスで定義してる bookmark テーブルは、 url テーブルの id と user テーブルの id とで関連付け出来るんで、 bookmark テーブルの Row オブジェクトから、それぞれのレコードを簡単に取れるようにしてみます。

実際以下するコードは下記のようなものになっています。

    add_method user => sub {
        my $row = shift;
        $row->get_model->lookup( user => $row->user_id );
    };

add_method の第一引数にメソッド名、第二引数に実際のコードリファレンスを渡します。

bookmark テーブルの Row クラスにメソッドを生やすだけなので、コードリファレンスの中身としては第一引数は Row オブジェクトそのものです。

第二第三以降は任意の引数がそのまま渡されますし、戻り値もそのまま戻されます。

Row オブジェクトには get_model という Row オブジェクトを作るのに使ったスキーマオブジェクトが取れるので get_model から利用できるスキーマオブジェクトを取り出して、それを使って lookup 検索をかけています。

(この get_model メソッドはさっき github に push したので CPAN の方では今現在利用できません。)

install_model bookmark の全体の定義は以下のようになります。

install_model bookmark => schema {
    key [qw/ url_id user_id /];
    index 'user_id';
    columns qw/ url_id user_id /;

    add_method user => sub {
        my $row = shift;
        $row->get_model->lookup( user => $row->user_id );
    };
};

使ってみる

使い方は簡単で bookmark テーブルの Row オブジェクトから生やしたメソッドを呼ぶだけです。

$row->user;

データの insert も含めたコード例としては以下のような感じです。

my $bookmark = MyBookmark->new;
$bookmark->set(
    user => 1 => { nickname => 'Yappo' }
);
$bookmark->set(
    bookmark => [1, 1]
);

my $bookmark_row = $bookmark->lookup( bookmark => [1, 1] );
my $user_row     = $bookmark_row->user;
print "nickname = " . $user_row->nickname . "\n";

実行結果は下記の通り。

nickname = Yappo

これだけじゃ DBIC で言うところの prefetch 相当の事は出来ませんが、ちょっとした関連データを取るコードがすっきり書けるようになりました。

おわりに

add_method を使うと、ちょっとしたメソッドを Row クラスに生やすことが出来ます。

今日のような単純なリレーションをはじめとして、カラムの値の単位変換などでも利用出来ます。

が、単位変換は別途 Inflation を利用した方がよいでしょう。

ということで今日はここまで。

追記 10/01/04

antipop さんが、メソッドを追加する別の方法を指摘してくださいました。

こっちの方法を使えば継承とかしてメソッドの使い回しがきくんすよね。。

すっかり忘れてた。

http://d.hatena.ne.jp/antipop/20100102/1262441380