Mixin 機能その1
はじめに
さて、昨日はレコード総数をとるための COUNT クエリを投げるのがめんどくさいというところで終わりました。
Data::Model にはスキーマクラスに任意のメソッドを生やす為の Mixin という仕組みがあります。
今日はその Mixin 機能を使って COUNT クエリを楽に発行できるようにしましょう。
Mixin を作る
mixin を作るためには以下のようなクラスを作ります。
package MyBookmark::Mixin::Count;
use strict;
use warnings;
sub register_method {
+{
count => \&count;,
};
}
sub count {
my($self, $model) = @_;
my $dbh = $self->get_driver($model)->r_handle;
my $sth = $dbh->prepare_cached(
'SELECT COUNT(*) AS count FROM ' . $model
);
$sth->execute;
my $count;
$sth->bind_columns(undef, \$count);
$count = 0 unless $sth->fetch;
$sth->finish;
return $count;
}
1;
昨日の COUNT クエリのためのコードにいくつかコードをくるんだ感じになりました。
Data::Model の Mixin として機能するためには register_method が定義されているだけで良いのです。
register_method は HASH リファレンスを返して、 key が生やしたいメソッド名を入れて value は、そのメソッドのコードリファレンスを渡します。
mixin で追加したメソッドの第一引数にはスキーマクラスのオブジェクト( MyBookmark->new した時のオブジェクト)が渡され、第二引数以降はユーザによって渡された引数がそのまま入ります。
Mixin をスキーマに割り当てる
mixin を作ったらスキーマクラスで使えるようにする必要があります。
例えば MyBookmark クラスに以下の一行を追加すればokです
use Data::Model::Mixin modules => ['+MyBookmark::Mixin::Count'];
ここで MyBookmark.pm の先頭は以下のようになってます。
package MyBookmark; use strict; use warnings; use base 'Data::Model'; use Data::Model::Schema; use Data::Model::Mixin modules => ['+MyBookmark::Mixin::Count'];
これだけです。
mixin のメソッドを使う
一度割り当てたら set/get/lookup メソッド等と同じように使えます。
my $count = $bookmark->count('user');
とするだけで、特定のテーブルの COUNT を行うことができます。
適当にレコードを作って COUNT するサンプルは下記の通り。
use strict;
use warnings;
use MyBookmark;
my $bookmark = MyBookmark->new;
$bookmark->set(
user => 1 => { nickname => 'Yappo' }
);
$bookmark->set(
user => 11 => { nickname => 'nekokak' }
);
$bookmark->set(
user => 101 => { nickname => 'kan' }
);
print "COUNT: " . $bookmark->count('user') . "\n";
実行結果
COUNT: 3
となれば成功です。
まとめ
今日はスキーマクラスにメソッドを生やす為の Mixin の作り方を紹介しました。
ただ、今回作った count は InnoDB だと悲惨なことになるので、特定のインデクスの結果を COUNT に取るようにしたい所ですが、それはまた今度。