« 9月7日の行動 | メイン | NONDRINKING »

2006年09月07日

[技術] Catalyst + Class::DBI で動作不良 (2)

昨日、Catalyst + Class::DBI 環境での不具合を書いたが取り急ぎ、回避方法(不具合現象の根本的な解決ではない)がわかった。

■不具合の発生する原因
Class::DBIのhas_many設定において、ロード時に外部参照テーブルの外部キーが正しく取得できないのが不具合の原因であった。その箇所は、Class::DBI::Relationship::HasMany.pmのremap_argument()にある以下の部分(33〜37行目)で、外部テーブルに対応するクラスに設定されているhas_a設定から、外部キーを取得するところで、肝心の設定内容を取得でいないためである。($f_keyに正しい値が入らない)

$f_key ||= do {
    my $meta = $f_class->meta_info('has_a');
    my ($col) = grep $meta->{$_}->foreign_class eq $class, keys %$meta;
       $col || $class->table_alias;
};

この箇所で、外部テーブルクラス($f_class)が未ロードであることを考慮して、26行目に以下のようにロードするための処理を呼び出している。

$class->_require_class($f_class);

本来なら、この_require_class()で、外部テーブルクラスがロードされるはずなのだが、なぜか正しくロードされていないため、33〜37行目の処理で$f_keyに正しい値がセットされない。

ちなみにモデルクラスのhas_many, has_aの設定は以下のようになっている。
 

呼び出し元クラス(Report)
__PACKAGE__->has_many(contacts => 'Contact');
外部クラス(Contact)
__PACKAGE__->has_a(reportid => 'Report');

HasManyのremap_argument()では上記のhas_many, has_aの設定から、f_keyとして、reportidを取得している。しかし、これが上手く行っていないのが、不具合の原因だ。

そこで、回避策として、呼び出し元クラスのhas_many設定で、明示的に外部キーを指定するようにした。

呼び出し元クラス(Report)
__PACKAGE__->has_many(contacts => 'Contact', 'reportid');

このようにしたところ、今まで不具合が発生していた場所で起動しても、正しいSQLが生成され、結果が表示されるようになった。

投稿者 nekobara : 2006年09月07日 10:23


コメント