日向夏特殊応援部隊

俺様向けメモ

DBIx::Class::ResultSetManagerが素敵な件

はじめに

DBIx::Class::ResultSetManagerを使うとTableクラスの中のメソッドとして、ResultSetの拡張を記述する事が出来ます。*1

ちなみにまだ実験段階のモジュールのようです。
あしからず。

以下ドキュメントのSYNOPSYSをそのまま。

# in a table class
__PACKAGE__->load_components(qw/ResultSetManager Core/); # note order!

# will be removed from the table class and inserted into a
# table-specific resultset class
sub search_by_year_desc : ResultSet {
  my $self = shift;
  my $cond = shift;
  my $attrs = shift || {};
  $attrs->{order_by} = 'year DESC';
  $self->search($cond, $attrs);
}

$rs = $schema->resultset('CD')->search_by_year_desc({ artist => 'Tool' });

Catalyst::Model::DBIC::Schemaとかをstaticでgenerateした場合、
tableクラスは作ってくれる物の、$c->model('Model::TableName')ってやった場合って
デフォルトのResultSetが取得されるだけになってます。

従ってResultSetクラスを作らずにResultSetを拡張するのに非常に便利。

DBIx::Classはattributeでの拡張が元々可能な設計!

あとDBIx::Classのソースを見ると書いてあるんですが、

sub MODIFY_CODE_ATTRIBUTES {
    my ($class,$code,@attrs) = @_;
    $class->mk_classdata('__attr_cache' => {})
      unless $class->can('__attr_cache');
    $class->__attr_cache->{$code} = [@attrs];
    return ();
}

sub _attr_cache {
    my $self = shift;
    my $cache = $self->can('__attr_cache') ? $self->__attr_cache : {};
    my $rest = eval { $self->next::method };
    return $@ ? $cache : { %$cache, %$rest };
}

と言う記述があるので。$class->__attr_cacheにはCODEに記述したattributeがキャッシュされていきます。

Class::Inspectorと組み合わせると、多分カッコいいモジュール作れそうな予感です。w

*1:CookBookにも載ってます