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 ##### CGI::Application community mailing list ################ ## ## ## To unsubscribe, or change your message delivery options, ## ## visit: http://www.erlbaum.net/mailman/listinfo/cgiapp ## ## ## ## Web archive: http://www.erlbaum.net/pipermail/cgiapp/ ## ## Wiki: http://cgiapp.erlbaum.net/ ## ## ## ################################################################