__PACKAGE__がうざいときにuse component;

DBIx::Classのシンタクスシュガーがほしいについて。とりあえずJifty::DBIとData::Modelについてはいずれ調べるとして,クラスメソッドのシンタクスシュガーを一般化するモジュールを書いた。

CPANにあげるようなものではないけど。
http://svn.coderepos.org/share/lang/perl/component

  package DB::Main::Artist;
  use component qw(DBIx::Class PK::Auto Core);

  table 'artist';
  add_columns qw/ artistid name /;
  set_primary_key 'artistid';
  has_many cds => 'DB::Main::CD';

  1;

内部でcaller()->load_components()してるだけなのでload_components()がないと動かない上,1パッケージにつき1度しかuse component;できないのが欠点だけど,まあ遊びなので。

component.pmで新しいのは,DSL風に"table 'artist'"としてもいいし,"__PACKAGE__->table('artist')"としてもいいところ。しかも,DSL風のシンタクスシュガーはレキシカルスコープなので,スコープの外からDB::Main::Artist::table()とかは呼べない。ただし,クラスメソッドとしては呼べる。

これは怪しいけどちゃんとしたPerlの仕様である。なんでこんなことができるのかというと,namespace::cleanに少し解説がある。
つまり"table 'artist'"というサブルーチン呼び出しがOPコードにコンパイルされると,そのOPコードは*DB::Main::Artist::tableという型グロブを参照する。そこで,OPコードのコンパイルが済んだ後にDB::Main::Artistパッケージからtableシンボルを削除すると,コンパイル済みのOPコードが参照する*DB::Main::Artist::tableはまだ生きているにもかかわらず,実行時にはその*DB::Main::Artist::tableが見えないということになるわけだ。

一方メソッド呼び出しは実行時にシンボルテーブルを探索するので,DB::Main::Artist->table()というコードが実行されるときには*DB::Main::Artist::tableは無事にスルーされ,親クラスのtable()メソッドが呼び出されるというわけ。