DBIx::Class 0.07がリリースされました
[Dbix-class] Announce: DBIx-Class-0.07
- Added InflateColumn::DateTime to auto create DateTime objects using
the appropriate DateTime::Format::* classin a database agnostic way
- Added ResultSetColumn to perform aggregate and other functions on
specific resultset columns
- Substantial refactor of ResultSet to to better handle more complex
joins and improve efficiency
- Rewrite of many_to_many, including helpers for adding/deleting
objects without dealing with the link table directly
このうちInflateColumn::DateTimeとResultSetColumnを試してみました。
DBIx::Class::InflateColumn::DateTime
InflateColumn::DateTimeはdatetime型のカラムに対して設定するとDateTimeクラスを使ったinflate/deflateをしてくれます。
テーブルはこんな感じ
create table albums (
id int not null auto_increment,
title varchar(255),
artist varchar(255),
price int,
created_on datetime,
modified_on datetime,
primary key (id)
);
スキーマクラス
CD.pm
package CD;
use strict;
use warnings;
use base qw/DBIx::Class::Schema/;
__PACKAGE__->load_classes();
1;
テーブルクラス
CD/Albums.pm
package CD::Albums;
use strict;
use warnings;
use base qw/DBIx::Class/;
use DateTime;
__PACKAGE__->load_components (qw/PK::Auto InflateColumn::DateTime Core/);
__PACKAGE__->table('albums');
__PACKAGE__->add_columns (
qw/id title artist price/,
created_on => {data_type => 'datetime'},
modified_on => {data_type => 'datetime'}
);
__PACKAGE__->set_primary_key('id');
1;
test.pl
use strict;
use warnings;
use CD;
use DateTime;
my $schema = CD->connect('dbi:mysql:cd', 'user', 'pass');
my $now = DateTime->now(time_zone => 'local');
$schema->resultset('Albums')->create({
title => 'hoge',
artist => 'foo',
price => 1980,
modified_on => $now,
created_on => $now
});
my $albums = $schema->resultset('Albums')->search({});
while (my $album = $albums->next) {
print $album->title . '/' .
$album->artist . "\t" .
$album->price . "\t" .
$album->created_on->ymd . "\t" .
$album->modified_on->ymd . "\n";
}
実行すると
$ perl test.pl
hoge / foo 1980 2006-07-25 2006-07-25
lyo katoさんが公開しているDBIx::Class::DateTimeColumnsは設定したカラムに対して作成時、更新時に自動的に現在時刻を入れてくれる機能があるのですが、これを実現するには以下のようにnewとupdateをオーバーライドするとできます。
CD/Albums.pm
package CD::Albums;
・・・
sub new {
my ( $class, $attrs, @rest ) = @_;
my $now = DateTime->now(time_zone => 'local');
$attrs->{created_on} = $now
unless defined($attrs->{created_on});
$attrs->{modified_on} = $now
unless defined($attrs->{modified_on});
return $class->next::method($attrs, @rest);
}
sub update {
my ( $class, $attrs, @rest ) = @_;
my $now = DateTime->now(time_zone => 'local');
$attrs->{modified_on} = $now
unless defined($attrs->{modified_on});
return $class->next::method($attrs, @rest);
}
ちょっと面倒。
DBIx::Class::ResultSetColumn
ResulSetColumnはカラムに対して便利なメソッドを追加してくれます。
上記で作ったスキーマを利用して
test2.pl
use strict;
use warnings;
use CD;
use DateTime;
my $schema = CD->connect('dbi:mysql:cd', 'user', 'pass');
$schema->storage->debug(1);
my $albums = $schema->resultset('Albums')->search({});
my $cols = $albums->get_column('price');
print "Min: " . $cols->min . "\n";
print "Max: " . $cols->max . "\n";
print "Sum: " . $cols->sum . "\n";
print "Avg: " . $cols->func('AVG') . "\n";
実行すると
$ perl test2.pl
SELECT MIN( price ) FROM albums me:
Min: 1980
SELECT MAX( price ) FROM albums me:
Max: 1980
SELECT MIN( price ) FROM albums me:
Sum: 1980
SELECT AVG( price ) FROM albums me:
Avg: 1980
統計情報を取りたいときにいちいちResultSetを回さなくていいので便利です。