Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I've been trying to learn the ins and outs of mod_perl and CGI::Application lately, and I've been puzzling over something. I could use; the advise of more enlightened minds then mine.

My plan is to use AUTOLOAD to ... well autoload C::A's run_modes. I put a file in a known location (say ./lib/menu.pl) and &lazy_loader requires it. I guess this kinda goes against the principle of C::A put it seems like a good idea. The application will have dozens of run modes and I'm just to lazy to keep filling out the dispatch table. This works OK, but I can't help but to think I missing something. Is this a bad idea?

Also, mod_perl seems a little buggy, in as much as every once in a while (when I'm making changes in one of the required .pl files) it randomly fails with 'cant find Foobar.pm in @INC' but Foobar is there and @INC is correct. I restart the server and everything works. I can't reproduce it, and I don't see any pattern, but it happens fairly frequently.

Any suggestions, advise, dope slaps?

#! /usr/bin/perl -w package Foobar; use strict; use base 'CGI::Application'; use Apache::Reload; sub setup { my $self = shift; $self->load_run_modes(); $self->start_mode('menu'); $self->run_modes("AUTOLOAD"=>\&lazy_loader); } # Add .pl files in ./lib for each run mode # This silly little sub (along with lazy_loader) will find and require + them. sub load_run_modes { my $self = shift; foreach (< ./lib/.*pl >) { /.*lib\/(\w+).pl/; require $_; } } # This is just to avoid having to add sub's to run_modes # see load_run_modes sub lazy_loader { no strict 'refs'; &{$_[1]}; use strict 'refs'; } 1;
Meanwhile in ./lib/menu.pl
sub menu { 'Ouch'; }

Replies are listed 'Best First'.
Re: CGI::Application musings
by ihb (Deacon) on May 30, 2005 at 00:36 UTC

      I don't think that CGI::Application::Dispatch will help in this situation. The op is trying to avoid having to fill out the $self->run_modes() hash and CGI::Application::Dispatch will not help to solve that. However, since the op is motivated by lazyness, CGI::Application::Dispatch is definately something that should be looked into!

      CGI::Application::Dispatch helps when you have several CGI::Application modules, and you are tired of writing stub CGI scripts to launch all the modules. It allows you to lauch multiple CGI::Application modules from a single CGI script (or mod_perl handler) by using the PATH_INFO of the URL.

      Update: I just re-read the question, and it looks like your suggestion is a good one. I missed the part of the code where the runmodes from a whole bunch of modules where loaded into the main CGI::Application module. Sorry for the confusion.

Re: CGI::Application musings
by cees (Curate) on May 30, 2005 at 01:49 UTC

    I think what you are looking for is CGI::Application::Plugin::AutoRunmode. What you are doing sounds inherantly dangerous. You are allowing the user to execute any function that you have loaded into memory (remember that you can fully qualify your functions by putting the package name in front of it, so the user isn't even limited to just your CGI::Application namespace).

    The way that CGI::Application::Plugin::AutoRunmode handles things is by using method attributes. Using your example, you would just do the following:

    use CGI::Application::Plugin::AutoRunmode qw [ cgiapp_prerun]; sub menu : Runmode { 'Ouch'; }

    Not only is that safer, but it is also a lot cleaner and simpler than your AUTOLOAD solution.

Re: CGI::Application musings
by dragonchild (Archbishop) on May 30, 2005 at 01:52 UTC
    In addition to the excellent suggestions you've already received, why are you putting all your runmodes in one class? Each C::A child should have between 4-10 runmodes with 12 being an absolute maximum. My average is around 5, my low is 2, and my high is 11.

    Those classes each represent one subsystem of your overall web application. If you find you're needing more runmodes than 12, then you should either consolidate some of the runmodes by abstracting out shared functionality or you should split some runmodes off into another class so that they're consolidated by functionality.


    • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
    • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"