« 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