[Catalyst] Sub-classing Application
J. Shirley
jshirley at gmail.com
Wed Dec 16 17:59:11 GMT 2009
On Wed, Dec 16, 2009 at 9:27 AM, Bill Moseley <moseley at hank.org> wrote:
>
>
> On Wed, Dec 16, 2009 at 8:31 AM, J. Shirley <jshirley at gmail.com> wrote:
>>
>>
>> The documentation seems quite sparse, but if you look at the source it
>> just essentially does:
>> my $locator = Module::Pluggable::Object->new(
>> search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
>> %$config
>> );
>>
>> If you have MyApp->config->{search_extra} = [ 'Foo::Controller',
>> 'Foo::Model' ]; it should DTRT.
>
> It almost works, but it sets up actions for both controllers using each
> controller's class.
>
> That is, if I start application Bar and pass in search_extra => [qw/
> Foo::Controller / ] then indeed actions from Foo::Controller::* will get
> added to the application.
>
> But, they are added with the Foo:: namespace. that is, that controller is
> not a parent-class of Bar::Controller::*.
>
> It also means I can't easly overide. If I have hello() in both thes
> controllers:
>
> Foo::Controller::Whatever::hello()
> Bar::Controller::Whatever::hello()
>
> I then get:
>
> [debug] Loaded Path actions:
> .-------------------------------------+--------------------------------------.
> | Path | Private
> |
> +-------------------------------------+--------------------------------------+
> | / | /index
> |
> | / | /index
> |
> | / | /default
> |
> | / | /default
> |
> | /whatever/hello | /whatever/hello
> |
> | /whatever/hello | /whatever/hello
> |
> | /whatever/howdy | /whatever/howdy
> |
> '-------------------------------------+--------------------------------------'
>
> So, I guess what I really would like is a way to have it load the Foo::*
> modules but register their actions in the associated Bar:: namespace
> so that /whatever/hello calls Bar::Whatever::hello but Foo::Whatever is the
> parent class if hello() doesn't exist in Bar.
>
> (That sentense make sense?)
>
> I guess that means when Foo::Controller::Whatever is found, register the
> actions in the Bar::Whatever namespace and push Foo::Whatever onto
> @Bar::Whatever::ISA.
>
>
> The problem I'm looking at is rebranding applications. In the past I've
> managed to modify config based on, say, domain name and use a different root
> (for templates, css, images, etc.) But, over time the application has to be
> forked due to changes in code. But, 90% of the controller code is still the
> same between the two applications.
>
> So, it would be handy to say, this application inheits from Foo, but these
> with a few methods added or overridden.
>
>
It seems you're after something that would best be accomplished using
roles that get composed into the controller.
http://search.cpan.org/~hkclark/Catalyst-Manual-5.8002/lib/Catalyst/Manual/CatalystAndMoose.pod#ROLES_AND_METHOD_MODIFIERS
I've done similar things (and maintain it) and the sections that I
refactored to use this method are much more maintainable (and using
Chained). When I just mix random things or maintain a copy'n'paste
swath, bad things happen.
Probably not an ideal answer, but I actually found the refactoring was
pretty easy.
Essentially: cp Controller/Foo.pm MyApp/Role/Controller/Foo.pm then
converting it to use Moose::Role syntax per the CatalystAndMoose pod,
then modifying everything to just do 'with Controller::Foo'; It's
hard-coded still, and not ideal, but for me at least it is
write-once-forget-forever (and I see exactly what is composed into the
class, which makes debugging easier).
That's about the best I have for you, sorry :)
-J
More information about the Catalyst
mailing list