On Fri, Jun 10, 2011 at 4:21 PM, Bill Moseley <[email protected]> wrote:

> I have an app "Foo" and would like to make a new application based on it
> called "Bar".
>
> Is there a better approach than making a copy and s/Foo/Bar/g in most
> directories (lib, t)?


This is probably not a full solution, but may get you on the path to one.

I had a similar problem at $work where we have a core Catalyst application,
but also needed the ability to install customer-specific components (either
completely new functionality, or overriding one of the core controllers),
and didn't want this to turn into a management nightmare (like
hand-replacing specific component files on certain customers' systems and
praying we remembered when upgrading them later, which is what we
unfortunately did with our ancient CGI-script-based "app").

Our Catalyst implementation looks something like this:

package My::App;

use Moose;
use Catalyst;

__PACKAGE__->config(
    customers => [qw/Initech/],
    setup_components => {
        except => qr/^My::App::(Controller|Model|View)::Customer::/,
    },
);

around locate_components => sub {
    my $orig  = shift;
    my $class = shift;
    my @comps = $class->$orig(@_);
    foreach my $customer (@{$class->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;
        }
    }
    return @comps;
};

The code above roughly does the following:

   - Find all components as Catalyst normally does
   - For each customer identifier, search a customer-specific component tree
   (My::App::(C|M|V)::Customer::$cust)
   - For each component found there, append it to the list of components to
   load
   - If the customer-specific component shares its class path with a core
   component, remove the core component from the load list (i.e.,
   ::Controller::Customer::Initech::Foo causes ::Controller::Foo to be skipped;
   the assumption is that the customer-specific module extends it or replaces
   it entirely)

If I had to adapt your problem to my problem, the core application would be
Foo, and our customer would be Bar.

I hope this gives you some ideas.

-- 
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