ここ数日のDBIx::Skinny

Wassrでつぶやいてたら取り込まれたり、githubのcollaboratorに入れてもらったのでpushしたりしたことのまとめ。

■$row->setの引数がhashからhashrefに変わった

before

$row->set($key => $val);

元々は単一のkeyでsetするのが基本、ということでhashだったらしいです。とは言え、複数でも問題なく使えてました。で、updateはhashrefを渡すので、それと統一された形です。

after

$row->set({ $key => $val });

CPANに上がってるのとインタフェースが変わってるので、要注意です。

■order_byの拡張

before

MyApp::DB->search($table, $where, { order_by => [ { id => 'desc' } ] });

hashrefをn個入れたarrayrefしか受け付けなかったのを、hashref単体や文字列でもorder_byできるようにしました。

after

MyApp::DB->search($table, $where, { order_by => 'name' });
MyApp::DB->search($table, $where, { order_by => { id => 'desc' } });

■$row->updateした時に自動でsetするように

before

use Test::More qw/no_plan/;

my $row = MyApp::DB->single($table, { id => 1 });
is $row->name, 'hoge';
$row->update({ name => 'fuga' });
is $row->name, 'fuga'; # failed, got 'hoge'

DBIx::Skinny::Rowのオブジェクトに対してupdateをかけた場合、DBのデータは更新されますが、$rowが持ってる値は更新されませんでした。なので、このテストは通りませんでした。

これはDBIx::Skinny::Rowが持ってるカラムのキャッシュがupdateでは更新されないためで、

$row->set({ name => 'fuga' });
$row->update;
is $row->name, 'fuga' # passed

と書く必要がありました。set呼ぶとキャッシュがクリアされるので、こっちはOK。

カラムのキャッシュと言っても、別にmemcachedとか使ってるわけじゃなくて、単にrowオブジェクトの中に値を持ってるだけです。$row->nameとか呼ぶ度にinflateするのが無駄なので、そこをキャッシュしてくれてるんですね。

とは言え、$row->updateにhashrefを投げた時にもキャッシュクリアして欲しいので、$row->updateした時に内部でsetも呼ぶようにさっき変更しました。なので、前述のテストも最新版だと通ります。

なんでこうなってるかと言うと、元々は

MyApp::DB->update({ name => 'fuga' }, { id => 1 });

って感じでRowオブジェクトを取らずに外からDBにアクセスするのがSkinnyのアプローチだったのかなと推察。