Resultクラスの拡張
Resultクラス、
カラムのinflate/deflate
$tweet->created_
Resultクラス内で
__PACKAGE__->inflate_column('column_name', {
inflate => sub {
# カラムデータからオブジェクトを作って返す
},
deflate => sub {
# オブジェクトからカラムデータを作って返す
},
});
という定義をすると、
# inflateされたPerlオブジェクトを返す
my $obj = $raw->column_name;
# Perlオブジェクトをカラムに入れる
$raw->column_name($obj);
このようにデータベースからPerlオブジェクトを取得したり、
たとえば、
use JSON;
__PACKAGE__->inflate_column('json', {
inflate => sub { decode_json(shift) },
deflate => sub { encode_json(shift) },
});
●日付のinflate/deflate
日付のような、
利用するのは簡単で、
__PACKAGE__->load_components(qw/InflateColumn::DateTime/);
と1行書くだけです。これを書くとdata_
created_date => {
data_type => 'DATETIME',
is_nullable => 0,
timezone => 'Asia/Tokyo',
},
●カラムの生データへのアクセス
inflate/
Result/ResultSetクラスに自分のメソッドを増やす
DBIx::Classが用意しているメソッドだけでなく、
# in My::Schema::Result::User
sub follow {
my ($self, $target) = @_;
$self->add_to_following_maps({
target => $target->id
});
}
このようにResultクラスやResultSetクラス上で独自のメソッドを定義すると、
# daisukeというユーザをfollow
my $daisuke = $user_rs->find({ username => 'daisuke' });
$user->follow($daisuke);
組み込みのメソッドを拡張する
ResultクラスやResultSetクラス内では独自のメソッドを定義できるだけではなく、
たとえばTweetクラスのようにデータ作成時刻を記録するcreated_
sub insert {
my $self = shift;
my $now = DateTime->now;
$self->created_date($now);
$self->modified_date($now);
$self->next::method(@_);
}
sub update {
my $self = shift;
$self->modified_date(DateTime->now);
$self->next::method(@_);
}
next::methodというメソッド呼び出しは、
ただ、
Resultクラス、
DBIx::Classハックのためのヒント
1ページ目で少し触れたnextによるメソッドチェインなどからもわかるように、
C3 MRO
DBIx::Classが一般的なPerlモジュールの構造と一番異なるのが、
DBIx::ClassではC3のメソッド解決のオーダー
またC3 MROは、
DBIx::Classのクラス構造
すべてのDBIx::ClassコンポーネントはClass::C3::Componentisedというクラスを継承しています。Class::C3::Componentisedのload_
load_
package My::Schema::Result::Tweet;
use base 'DBIx::Class::Core';
__PACKAGE__->load_components(qw/InflateColumn::DateTime/);
このResult::TweetクラスはDBIx::Class::Coreを継承していますが、

さらにDBIx::Class::Coreはその中で、
__PACKAGE__->load_components(qw/
Relationship
InflateColumn
PK::Auto
PK
Row
ResultSourceProxy::Table
/);
をしています。したがって最終的には図3のようなクラス構造になっていることになります。この状態でTweetテーブルからのC3メソッド解決の順番は、
- ① My::Schema::Result::Album
- ② DBIx::Class::InateColumn::DateTime
- ③ DBIx::Class::Core
- ④ DBIx::Class::Relationship
- ⑤ DBIx::Class::InateColumn
- ⑥ DBIx::Class::PK::Auto
- ⑦ DBIx::Class::PK
- ⑧ DBIx::Class::Row
- ⑨ DBIx::Class::ResultSourceProxy::Table
となります。

前節でResultクラスのupdateメソッドを上書きしましたが、
まとめ
DBIx::Classは機能が豊富な分、
本稿ではDBIx::Classのすべての機能はとても紹介しきれませんでした。興味の持った方はぜひドキュメントを参照してください。
次回の執筆者は和田裕介