Class::DBIのinflate、deflateについて
inflateは、引いてきたレコードのカラムの値をオブジェクトでラップするために使います。これは知っていたのですが、deflateは関数をなにも指定しないときに呼ばれる関数だと思っていました。(今思うとかなり恥しい…)しかし、実際のdeflateの意味はまったく違うというのがわかりました。
結論から言うと、deflateはレコードをcreateするときに発動するもので、deflateを設定したカラムに あるオブジェクトを渡すとそのインスタンスに対してdeflateで指定した関数もしくはcoderefが呼ばれるという仕組みのようです。
つまり下記のようなhas_aを定義したFooというデータクラスがあったとして
__PACKAGE__->has_a( dt => 'Time::Piece', inflate => sub { Time::Piece->strptime(shift, '%Y-%m-%d') }, deflate => 'ymd', );このデータクラスを使用したプログラムの中で
my $dt = Time::Piece->new; Foo->create({ dt => $dt, })とやると、createでdtに渡した、$dtに対してdeflateで指定したymd関数を使い、$dt->ymdの返り値がdtカラムに格納されるということです。
Class::DBIやClass::DBI::Relationship::HasAを徘徊してみると、このdeflateはdeflate_for_createかdeflate_for_updateのときのトリガとして登録されるようで、しかもcreate時に渡された値(上記の場合の$dt)がオブジェクトなどのrefの評価がtrueになる場合のみ発動するもののようです。
ちなみに、もしdeflateにcoderefが指定されていた場合には、そのcoderefに引数として$dtが渡ってきますので、そこでよしなに処理をしてreturnをしたものがINSERTされます。つまり、下記のようにすると先程のコードと同じ動作になります。
__PACKAGE__->has_a( dt => 'Time::Piece', inflate => sub { Time::Piece->strptime(shift, '%Y-%m-%d') }, deflate => sub { shift->ymd }, );