[Catalyst] Base controllers and multiple inheritance
Byron Young
Byron.Young at riverbed.com
Wed Mar 5 22:29:30 GMT 2008
Byron Young wrote:
> Hi,
>
> I've been using Catalyst for a project and decided to make some base
> controllers for common functionality. So far I've made two: CRUD, and
> List, for standard database operations and for sortable, paged
> listings
> of data. They work fine on their own but I'm running into trouble
> with multiple inheritance. If I have a controller for some database
> table
> that I want to inherit the actions from both CRUD and List, only the
> first one inherited will initialize properly.
>
> The inheritance looks like this:
>
> Catalyst::Controller
> / \
> / \
> / \
> / Catalyst::Controller::HTML::FormFu
> / |
> MyApp::Base::Controller::List |
> \ |
> \ MyApp::Base::Controller::CRUD
> \ /
> \ /
> \ /
> MyApp::Controller::SomeDatabaseTable
>
>
> Each of the controller base classes has a new() method which sets up
> config data and does error checking and whatnot. If I inherit both of
> my base classes, only new() on the first inherited is called. I've
> tried calling $class->NEXT::new(@_) in each, and I've also tried
> Class::C3's $class->maybe::next::method(@_), but new() is still not
> called down the second inheritance chain. When I tried the Class::C3
> approach I called Class::C3::initialize() in MyApp.pm - I wasn't sure
> where to call it so I tried before and after MyApp->setup() - still no
> luck.
>
> Can somebody tell me why new() isn't called down both paths?
>
Sorry for the pestering, but allow me to provide some more info. I was
hoping to have my controllers inherit a number of base controllers that
I've got planned, but maybe I'm taking the wrong approach? Seems like
this is probably a pretty common thing, but I haven't found anything
about it in the email list backlogs or anywhere else, except a comment
from jrockaway saying that you can inherit multiple base classes.
Here are my new() methods in the various classes:
---
package MyApp::Controller::SomeController;
use base qw/
MyApp::Base::Controller::CRUD
MyApp::Base::Controller::List
/;
use Class::C3;
sub new {
my $class = shift;
my ($c) = @_;
my $self = $class->maybe::next::method(@_);
$c->log->debug("in SomeController::new");
return $self;
}
---
package MyApp::Base::Controller::List;
use base qw( Catalyst::Controller Class::Accessor::Fast );
use Class::C3;
__PACKAGE__->mk_accessors(qw( _list_config ));
sub new {
my $class = shift;
my ($c) = @_;
my $self = $class->maybe::next::method(@_);
$c->log->debug("in List::new");
$self->_list_setup( $c );
return $self;
}
---
package MyApp::Base::Controller::CRUD;
use base qw( Catalyst::Controller::HTML::FormFu );
use Class::C3;
__PACKAGE__->mk_accessors(qw( _crud_config ));
sub new {
my $class = shift;
my ($c) = @_;
my $self = $class->maybe::next::method(@_);
$c->log->debug("in CRUD::new");
$self->_crud_setup( $c );
return $self;
}
I also added a $c->log->debug("in FormFu::new") in
Catalyst::Controller::HTML::FormFu::new(). Here's the output:
[debug] in FormFu::new
[debug] in CRUD::new
[debug] in CRUD::_crud_setup
[debug] in SomeController::new
List's new() is not called in that case.
Here's what happens when I inherit List before CRUD in SomeController:
[debug] in FormFu::new
[debug] in CRUD::new
[debug] in CRUD::_crud_setup
[debug] in List::new
[debug] in List::_list_setup
[debug] in TestModule::new
Everything looks good, right? My List actions work! However, the CRUD
actions don't work because the FormConfig actions seem to have been
ignored -- $c->stash->{form} is undef :(
Does anyone have any suggestions? Should I just forego using new() and
do initial setup the first time auto() is called in each of my base
controllers?
Thanks,
Byron
More information about the Catalyst
mailing list