[cgiapp] CGI::Application status update from the maintainer
Rhesa Rozendaal
perl at rhesa.com
Thu Sep 6 13:04:24 EDT 2012
On 09/06/2012 04:48 PM, B. Estrade wrote:
> You're limited to 2 generations below CAP if you want to subclass
> without explicitly calling on SUPER because you have 2 explicit
> methods -cgiapp_init and setup. I am suggesting a way to provide any
> number of generations without having to call on SUPER.
You're not limited to 2 levels of inheritance. The grandchild's SUPER
calls the child's method, and the child's SUPER calls the parent's
method. It'll work the same even when you add a grandchild. (At some
point I'd start asking myself if inheritance is really the way I'd want
to structure my application).
> Here is my real world use case. I split my applications into 2 parts;
> one amounts to the UI payload delivery, basically HTML that makes all
> calls asynchronously. The other is strictly non-UI and handles only
> asynchronous requests (i.e., the "REST" API). And I typically have
> this hierarchy:
>
> 1. WebCommon.pm (ISA CGI::Application; implements Authentication and common run modes)
> 2. WebApp.pm (ISA WebCommon; base class for the UI delivery or initial "view")
> 3. WebAPI.pm (ISA WebCommon; base class for the "REST" API)
>
>>From there, I may have another or even another 2 levels of WebApps or
> WebAPIs. In WebCommon.pm, I define cgiapp_init; in WebApps.pm and
> WebAPI.pm, I define a setup. Beyond that, I redefine setup with a call
> to $self->SUPER::setup - not something I really like doing.
You'd be better off setting up your runmodes in an init hook. That's the
way I do it in CA::Plugin::RunmodeDeclare.
package WebCommon;
use base 'CGI::Application';
__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});
package WebAPI;
use base 'WebCommon';
__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});
package WebAPI::Stuff;
use base 'WebAPI';
__PACKAGE__->add_callback( init => sub {
$_[0]->run_modes([ ... ]);
});
Then WebAPI has all the run modes of WebCommon, as well as its own run
modes. And WebAPI::Stuff has those of WebAPI and its own.
However, I'd ask myself if I really want to have all those parent run
modes in the child app.
> I want to use CGI::Simple, but do not want to enable uploads app-wide.
> I have a subclass (WebAPI::UploadApp, say) where I do want to enable
> uploads.
>
> In WebCommon.pm, I have to do this:
>
> our $cgi; #= CGI::Simple->new;
Don't do this. You need a query object that's an attribute of the
current CA object. A package variable is going to have too wide a scope.
> sub cgiapp_get_query {
> use CGI::Simple ();
> $cgi = CGI::Simple->new();
> return $cgi;
> }
This is better written as:
sub cgiapp_get_query {
use CGI::Simple;
return CGI::Simple->new;
}
> Then in order to override that CGI::Simple to enable uploads, in
> WebAPI::UploadApp, I have to do this:
>
> sub cgiapp_get_query {
> my $self = shift;
> use CGI::Simple ();
> $CGI::Simple::DISABLE_UPLOADS = 0;
> $self::SUPER::cgi = CGI::Simple->new();
> return $self::SUPER::cgi;
> }
That code makes little sense. cgiapp_get_query is supposed to return a
CGI compatible object. It's not supposed to change variables in another
package.
This is what you should do instead:
sub cgiapp_get_query {
local $CGI::Simple::DISABLE_UPLOADS = 0;
return $_[0]->SUPER::cgiapp_get_query;
}
> Granted, there is probably a more correct, cleaner, or better way to do
> this; if so, I am all ears.
The only ugly thing about that is that package variable to influence
upload behavior. It'd be prettier if CGI::Simple had an accessor for
that, or a constructor argument. That's what you get for trying to be
compatible with CGI.pm I guess ;)
rhesa
More information about the cgiapp
mailing list