Moose/Mouseのregister_implementationで短縮名を登録する時のファイル配置ってどうするんだろ
Moose::Cookbook::Meta::Recipe3みたいに、自前のTraitを作って、それをregister_implementationで短縮名でアクセス可能にする場合って、
- MyApp::Meta::Attribute::Trait::XXXX
- Moose::Meta::Attribute::Custom::Trait::XXXX
のファイルはどういう配置にするのがいいんだろう。
サンプルみたいにアプリのベースクラスとかに適当に埋め込んでしまえば話は早いんだけど、それもどうなのという気はする。
Moose/Meta/Attribute/Custom/Trait/XXXX.pmとか作っちゃうと、独自のTraitとか作るモジュールをインストールする度に、Mooseディレクトリ以下にMoose本体とは関係ないファイルが入ってしまうので、それも嫌な感じ。それに、Any::Moose対応しようと思ったら、Mouse/Meta/Attribute/Custom/Trait/XXXX.pmも配置することになって更に嫌な空気が漂ってくる。
Custom/にいろんな物が入ってくる前提で、Moose::Meta::Attribute::Nativeという名前区間が用意されてるのかも知れないけど、Customの中で他のモジュールと衝突する可能性も高いわけで、そこにファイルを置くのはやっぱり気が進まない。
MyApp/Meta/Attribute/Trait/XXXX.pmの中で解決できればいいけど、
has hoge => ( traits => [qw/XXXX/], is => 'rw', isa => 'Str', );
と書いた時に先に呼ばれるのはMoose::Meta::Attribute::Custom::Trait::XXXXの方なので、そいつがrequireできないとエラーで落ちてしまう。かと言って、おとなしく traits => [qw/MyApp::Meta::Attribute::Trait::XXXX/] とか書くのもダルい。
今のところ、MyApp/Meta/Attribute/Trait/XXXX.pmを
package MyApp::Meta::Attribute::Trait::XXXX; use Any::Moose '::Role'; # acutual trait implementation local $@; eval "package " . any_moose . "::Meta::Attribute::Custom::Trait::XXXX;\n". "sub register_implementation {'MyApp::Meta::Attribute::Trait::XXXX'}"; die $@ if $@; 1;
みたいに書いて、起点になるクラスで
package MyApp; use MyApp::Meta::Attribute::Trait::XXXX;
とかで事前にロードするようにしてるけど、これもどうにもまだるっこしい感が抜けない。
MyApp/Meta/*/Custom/以下のファイルを洗って、動的に組み込むローダとか作っちゃうのも一つの方法なのかも知れないけど、そもそもこのアプローチがいいのかどうか分からん。自前のTraitとか定義しまくってそうなモジュールを覗いてみよう。
#以下、追記
KiokuDBとかそのへんやってそうだと思って収録モジュール一覧を見てみたら、Moose::Meta::Attribute::Custom::Trait::KiokuDB::DoNotSerializeとLazyが入ってるのを確認した。
そうか、Custom::Trait直下じゃなくて、その下に自分のモジュール名で区切るのね。なるほど。で、SYNOPSISにあるように、
has bar => ( traits => [qw(KiokuDB::DoNotSerialize)],
という名前で呼び出すと。モジュール自身の名前空間が深いとtraits書くの面倒臭そうだけど、そこは仕方ないか。
これを見た感じだと、Any::Moose対応したい場合はMouse::Meta::も作っておくのが妥当なやり方なのかなー。
(10/07追記)MooseX::AttributeHelpersに同梱されてるMoose::Meta::Attribute::Custom::Collection::Arrayでは、MooseX/AttributeHelpers/Collection/Array.pmの中に
# register the alias ... package Moose::Meta::Attribute::Custom::Collection::Array; sub register_implementation { 'MooseX::AttributeHelpers::Collection::Array' }
と書いてalias設定してますね。代表的なMooseXモジュールでこういうアプローチを取ってるということは、筋の悪いやり方ではないのかな。ちょっと安心した。