On Mon, Jul 18, 2011 at 11:26 AM, Rodrigo <[email protected]> wrote:

> We're using 1) search_extra => [ 'MyAppX' ], as an add-on, non core
> namespace 2) {setup_components}->{except} 3) an around 'locate_components'
> to filter components in a special mode (which is used under a special flag
> which is not being really as far as I remember).
>
> if( $ENV{YELLOW_VERSION} ) {
>    around 'locate_components' => sub {
>         my $orig = shift;
>         grep !/Blue/, $orig->( @_ );
>    };
> }
>
>
>
This is pretty similar to how we were using it.  In our case we have a core
application but need to be able to inject replacement components for
specific clients.  Originally we just added the customer's namespace with
search_extra, but later realized that it didn't quite work as intended -- we
wanted to replace a component and that loaded both instead.  Combining
search_extra and except worked but was spaghetti code because of the dynamic
nature.  So we did an override of locate_components instead.

Suppose an app tree like so:

MyApp::Controller::Foo::Bar
MyApp::Controller::Customer::Initech::Foo::Bar

Our loading routine looks like this ($CONFIG here is a config file singleton
class that I hope goes away whenever Bread::Board makes it into Catalyst
core):

__PACKAGE__->config({
    setup_components => {
        except => qr/^MyApp::(?:Controller|Model|View)::Customer::/,
    },
});

mangle_return locate_components => sub {
    my($class,@comps) = @_;
    foreach my $customer (@{$CONFIG->customers}) {
        my @paths = qw( ::Controller ::Model ::View );
        my $locator = Module::Pluggable::Object->new(
            search_path => [ map {
s/^::(.*)/${class}::$1::Customer::${customer}/; $_; } @paths ],
        );
        foreach my $comp ($locator->plugins) {
            my $replace_class = $comp;
            $replace_class =~ s/::Customer::${customer}//;
            @comps = grep {$_ ne $replace_class} @comps;
            push @comps, $comp;
            __PACKAGE__->config({
                Catalyst::Utils::class2classsuffix($comp) => {
                    path => Catalyst::Utils::class2prefix($replace_class),
                },
            });
        }
    }
    return @comps;
};

This does three things if we set customer=Initech:

   1. Adds Controller::Customer::Initech::Foo::Bar to the load list
   2. Removes Controller::Foo::Bar from the load list
   3. Adjusts public path for Controller::Customer::Initech::Foo::Bar to
   replace the original controller

-- 
Stephen Clouse <[email protected]>
_______________________________________________
List: [email protected]
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/

Reply via email to