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 に取るようにしたい所ですが、それはまた今度。