カラムの定義を使いまわす3 Alias との連携B!

はじめに

本日で Column Sugar 集中講座最終日です。気合入れて行きましょう。

前回では Column.pm に Column Sugar の定義を移動してきました、記憶力の良い方は覚えているでしょうが Alias Column の時に例題で出していた global.epoch も移行していました。

global.epoch は create_dt という alias を張って DateTime で inflate してました。以下のような感じです。

install_model bookmark => schema {
# 略
    column 'global.epoch' => 'create_at' => {
        default => sub { time() },
    };
    alias_column create_at => create_dt => {
        inflate => 'DateTime',
    };

これとおんなじ事を diary でもやりたくなると

install_model create => schema {
# 略
    column 'global.epoch' => 'create_at' => {
        default => sub { time() },
    };
    alias_column create_at => create_dt => {
        inflate => 'DateTime',
    };

のようにおんなじコピペだらけになってしまいます。。。。

そこで登場するのが Column Sugar の Alias 設定です。

定義する

まずは Column Sugar の定義を変更します。

前回までは以下の形だったのを

column_sugar 'global.epoch'
    => int => {
        required => 1,
        unsigned => 1,
    };

次のように変更します。

column_sugar 'global.epoch'
    => int => {
        required => 1,
        unsigned => 1,
        alias => {
            epoch_dt => {
                inflate => 'DateTime',
            },
            epoch_dt_utc => {
                inflate => 'DateTimeUTC',
            },
            epoch_dt_jst => {
                inflate => 'DateTimeJST',
            },
        },

    };

alias という値を追加します。ここで与える HASH リファレンスは aliased_name => \%append_params という形式になっています。

新しいエイリアスカラム名を key にして、それに対する追加カラム定義を value とした HASH リファレンスです。

HASH リファレンスなので、複数の定義も同時に行えるので epoch_dt, epoch_dt_jst, epoch_dt_utc と作ってみました。

DateTimeUTC, DateTimeJST それぞれの Inflate 定義の中身は割愛します。

定義を利用する

こうして作ったエイリアス定義済みの Column Sugar を使ってみましょう。

もちろん

    column 'global.epoch' => 'create_at' => {
        default => sub { time() },
    };

すれば, table.create_at という形で使えます。使えますが、 alias されたカラムを使う時は $table->create_dt とかなって欲しいのに $table->epoch_dt とかになってしまいます。

これはちょっと混乱して大変ですよね。

なので、この Column Sugar で定義されたエイリアスカラムのカラム名を変更する仕組みも用意されています。

下記のようにして column 定義することによりリネームできます。

    column 'global.epoch' => 'create_at' => {
        default      => sub { time() },
        alias_rename => {
            epoch_dt     => 'create_dt',
            epoch_dt_utc => 'create_dt_utc',
            epoch_dt_jst => 'create_dt_jst',
        },
    };

column 定義の追加定義欄に alias_rename という key で HASH リファレンスを渡します。

HASH リファレンスの内容は、元のエイリアス名 => リネーム後のエイリアス名 という形です。これも複数個指定可能です。

使ってみる

ここまで準備できれば、あとは何も考える必要がありません。

alias されたカラムメソッドを使うだけです。

複数にエイリアスを張っていた時に、どれかのエイリアスの値を変更してもきちんとすべてのエイリアスの値は変更されています。

試しに以下のように使ってみますか。

    my $yappo = $bookmark->set( user => { nickname => 'Yappo' } );
    my $diary = $diary->set(
        diary => {
            user_id => $yappo->id,
        }
    );

    printf "create_at    : %s\n", $diary->create_at;
    printf "create_dt    : %s\n", $diary->create_dt;
    printf "create_dt_utc: %s\n", $diary->create_dt_utc;
    printf "create_dt_jst: %s\n", $diary->create_dt_jst;

    # create_dt_jst から生えてるメソッドを変えても Data::Model は検知できないので
    # 他のエイリアスに値が反映されないので、意図的に set しなおしてます
    $diary->create_dt_jst(
        $diary->create_dt_jst->
            set_year(2012)->set_month(12)->set_day(21)->
                set_hour(12)->set_minute(0)->set_second(0)
    );
    print "\nchange ddate\n";

    printf "create_at    : %s\n", $diary->create_at;
    printf "create_dt    : %s\n", $diary->create_dt;
    printf "create_dt_utc: %s\n", $diary->create_dt_utc;
    printf "create_dt_jst: %s\n", $diary->create_dt_jst;

実行した結果は下記のようになります。

create_at    : 1261383942
create_dt    : 2009-12-21T08:25:42
create_dt_utc: 2009-12-21T08:25:42
create_dt_jst: 2009-12-21T17:25:42

change ddate
create_at    : 1356058800
create_dt    : 2012-12-21T03:00:00
create_dt_utc: 2012-12-21T03:00:00
create_dt_jst: 2012-12-21T12:00:00

create_dt_jst を変えただけなのに、 create_at, create_dt, create_dt_utc と全てが変更されてる事がわかりますね。

まとめ

本日までで Data::Model のユニークな Column Sugar 並びに Alias Column についての紹介をしました。

他の ORM よりも柔軟にかつ簡単に役割を追加できる事がわかったとおもいます。

このあたりの機能はきちんとテストケースが書かれているので安心して利用できます。

という事で次回からはまた別の方面の紹介をします。