On Fri, Jun 10, 2011 at 4:21 PM, Bill Moseley 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.