How to add runmodes to a CGI::Application
There really are a ton of messy ways to tinker with adding runmodes to CGI::Application.
I tried a lot of different things, succesfully, strangely, even ‘cleverly’.
If you have a plugin that is being ‘use’d, you should have an import function.
Via Callback
package CGI::Application::Plugin::Cakes;
use strict;
use Exporter;
use vars qw(@EXPORT @ISA);
@EXPORT = qw(view_cakes _find_cakes find_old_cakes);
@ISA = qw/Exporter/;
sub import {
my $caller = scalar(caller);
$caller->add_callback( 'init', \&_register_runmodes );
goto &Exporter::import;
}
sub _register_runmodes {
my $self = shift;
$self->run_modes([qw(view_cakes find_old_cakes)]);
}
sub view_cakes {
my $self = shift;
return 'Cakes...';
}
sub find_old_cakes {
my $self = shift;
my $cakes = $self->_find_cakes;
return "Cakes... @$cakes";
}
sub _find_cakes {
my $self = shift;
return [qw(strawberry vanilla raspberry)];
}
Now, what is most crucial here is the import function.. You can also write the same as above in this alternate way:
sub import {
my $caller = scalar(caller);
$caller->add_callback(
'init',
sub {
my $self = shift;
$self->run_modes([qw(view_cakes find_old_cakes)]);
},
);
goto &Exporter::import;
}
Now, keep in mind, this is not a callback tutorial. But essentially, the syntax is
$YOUR_CGIAPP_CLASS->add_callback( $STAGE_IN_CGIAPP, $REF_TO_METHOD );
Now, what confused me a lot, was that you can make this be a class method or an object method.
ANd I felt like if I did a class method, I could not affect my object! Right? Actually, wrong. You can set callbacks at the class level, which will run for the object. Notice that view_cakes and find_old_cakes are object methods, but we inserted a callback to the class.
Why init instead of prerun?
If you add a callback hook to init, the runmodes will be available before you run() the instance.
This may be desirable for testing. Or maybe you have a self generating option menu, that reads the runmodes and offers them as links… hmmm….
What is the class?
The class is the package that defines your CGI::Application, where you have
package My::App;.
use base 'CGI::Application';
Jesse Erlbaum code helped me figure this out.
