Controllerなどの機能拡張をMooseのRoleで行う - その1
http://dann.g.hatena.ne.jp/dann/20080605/p5
で書いていたものですが、ここに書いていたアイデアの実装を用意してみました。
Controllerのpluginという形で実現するために、moose branchのcatalystにパッチをあてています。setup_actionsの後でRoleをconsumeしないと都合がわるいので、本体にパッチをあてています。
*************** *** 932,940 **** --- 932,951 ---- } $class->log->_flush() if $class->log->can('_flush'); + $class->setup_component_pluigns; $class->setup_finished(1); } + sub setup_component_pluigns { + my $class = shift; + foreach my $component ( keys %{ $class->components } ) { + my $component_instance = $class->components->{$component}; + if ( $component_instance->can('load_plugins') ) { + $component_instance->load_plugins; + } + } + } + =head2 $c->uri_for( $path, @args?, \%query_values? )
以下がBaseのController。
今は実験でベースのControllerでやってるけれど、多分、pluginをロードするところとかは、Catalyst::Componentレベルでするのがいいんだろうなぁと。Component用のPluginのような概念を導入したいなぁと。
package MyApp::BaseController; use Moose; BEGIN { extends 'Catalyst::Controller'; } # 多分ここらはCatalyst::Componentに移動させるのがよい with 'MooseX::Object::Pluggable'; has '+_plugin_app_ns' => (default => sub {['MyApp::Controller']}); sub load_plugins { my $self = shift; $self->load_plugin($_) for qw(Example); } sub index : Path Args(0) { my ( $self, $c ) = @_; # Hello World $c->response->body( $c->welcome_message ); } sub default : Path { my ( $self, $c ) = @_; $c->response->body( 'Page not found' ); $c->response->status(404); } 1;
以下、Controller
package MyApp::Controller::Example; use Moose; BEGIN { extends 'MyApp::BaseController'; } sub hoge : Local { my ($self, $c) =@_; $self->hello; } 1;
Controller用Plugin
package MyApp::Controller::Plugin::Example; use Moose::Role; sub hello { my ($self, $c) = @_; warn 'hello'; } 1;
TODO
- Catalyst::Componentレベルにpluginをロードする仕組みをもっていった場合の仕様決め
- メソッドバッティング時のaliasの仕様検討
- Component初期化時に、config読んだりとかっていうのを多分したいので、どこにhookさせるかの検討。Componentの既存メソッドにフックさせるか、新しくplugin用にhookさせるメソッドを用意させるかどっちか。