[cgiapp] Subclassing form

2002-06-10 Thread Seb

I'm just looking into CGI::Application, and after reading the pod and
viewing the code, I have two main questions...

(1) Should there be a NO_HEADERS and/or NO_OUTPUT (or similar) parameter
that the run() method takes? I ask for two reasons:

A. If I want to override the run method, for instance to print a
standard header/footer each time the app is run(), I would imagine that
it go like this:

  package My::App;
  use base 'CGI::Application';
  sub new {
my $class = shift;
my $s = $class-SUPER::new(@_);
$s-param('header' = $s-load_tmpl('header_common.html'));
$s-param('footer' = $s-load_tmpl('footer_common.html'));
return $s;
  }
  sub run {
my $s = shift;
print $s-_send_headers(); # Shouldn't this be a public method?

 # Print the head template
print $s-param('header');

 # Now call C::A's run method...
$s-SUPER::run(NO_HEADERS= 1);
 # or maybe...
print $s-SUPER::run(NO_HEADERS= 1, NO_OUTPUT = 1);
 # or even
$s-param('NO_HEADERS' = 1);
$s-SUPER::run();
 
# Now print the footer template
print $s-param('footer');
  }

B. If I have a hierarchy of C::A objects, the second (or third, gasp)
won't need to print an HTTP header at all.


(2) Lastly, on the heels of #B above:

How do _you_ implement an app hierarchy?

An application has different modules (sectional groupings of
functionality.) Sales, Inventory, Reports, etc, each having it's own set
of run-modes, or even sub-modules with sub-run-modes. I'd like to use
the same URL for the whole shebang.

I envision the base app's run-mode being a param called module with a
value like sales, then the base app can dynamically load the proper
'sub app' code and object, then that $subapp runs off with a second
traditional run-mode to do stuff.

Or should I just use run-mode values like: 
'Parts_Save' or 'Jobs_List' or 'Reports_JobTotals'
Then I could use $app-prerun() to trim off the first part, load the
specified code library, then run prerun_mode to save the trimmed run-mode
back to app object.

Am I way off base?

TIA

Sebastian


-
Web Archive:  http://www.mail-archive.com/cgiapp@lists.vm.com/
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




Re: [cgiapp] Subclassing form, futher thoughts

2002-06-12 Thread Seb

On Wed, 12 Jun 2002 11:15:01 -0400, Jesse Erlbaum [EMAIL PROTECTED] spoke
gently:
 Hi Sebastian --
 
  Now, my index.cgi would look like this:
  
  #!/usr/bin/perl
  use CGI qw(:standard);
  my $q = new CGI;
  my $modules = {
 sales = 'Sales',
 invent = 'Inventory',
 },
  };
  # Set a default
  $q-param('mod' = 'main')
 unless $q-param('mod');
  # Dynamically pull in the right section's module
  require ComponentManager/$modules-{$q-param('mod')}{load}.pm;
  # And fire it off
  my $app = 
  ComponentManager::$modules-{$q-param('mod')}{load}-new($q);
  $app-run();
 
 
 It looks like you're well on your way to building quite the Rube Goldberg
 machine!  If I understand what you're trying to do, if you want to run your
 Sales app, you would make a request like this:
 
   http://my.site/index.cgi?mod=sales
 
 
  ...For Inventory, you would do this:
 
   http://my.site/index.cgi?mod=invent
 
 
 Tell me -- what is the advantage of doing that instead of doing:
 
   http://my.site/sales.cgi
   http://my.site/invent.cgi

 
 The latter would have two advantages.  First, this is how CGI::Application
 (or a sub-class thereof) wants to work.  Second, your instance script
 (sales.cgi or invent.cgi -- instead of index.cgi) becomes MUCH more
 simple:
 
 #!/usr/bin/perl -w
 use Sales;
 my $app = Sales;
 $app-run();

The primary loss is the single point of access. I could live with that,
and simple is Good(tm), but when I see a dozen nearly identical CGI
scripts in a directory I don't think simple, I think Hmmm, _one_
would be better.

 What could be more simple than that?  What does this system NOT do that your
 system does?
 
 I would seriously consider taking about twelve paces BACK and re-evaluating
 your architecture.  CGI::Application is intended to make your code EASY --
 not turn it into a interconnected snarl of undocumented dependencies.  In
 general, if your instance script looks more complicated than what I've
 written above, you're probably doing something wrong.

Architecturally, my example above is actually quite simple, and could
easily work in a single pm file, using base run-modes like 'SALES_LIST'
or 'INVENT_SAVEITEM'...etc. I only implemented the dynamic loading to
ease administration, personally I hate working in files longer that a
few thousand lines, and this project will easily outgrow that in total.

  On another note, I would however like to pass html to run() at the
  base-class level, and have it place it in the output appropriately.
  There is currently no way to do that gracefully, because the http
  headers are built into the run method.
 
 Why on earth would you want to put *ANY* HTML in your code?  And assuming
 you have a good reason, why would you pass it through run()?

I guess I was not clear. I'm not putting html in my code. The desired
result is that I want to print a common header, without specifying it
each time in each run-mode sub. I think the easiest way would be to
allow cgiapp_prerun() to optionally return html, _just like any other
runmode does_.  C::A-run() could print it just before it prints the
runmode sub's output, thereby providing a hook for for printing common
content each time.

 
 Don't try to override the run() method.  Don't do it!  It is not intended to
 be used this way.  It may change in future version.  Heck, I might change it
 out of spite! :-)

:)

 
  Another possibility might be to, within the run() sub, simply 
  store the
  return value of cgiapp_prerun(), to be output just before the 
  run-mode's
  return value. That would solve the header problem, and for any common
  footers we could just use teardown().
 
 There are a lot of ways to do what you want to do without breaking the
 CGI::Application architecture all over the place.  For starters,
 HTML::Template supports a TMPL_INCLUDE tag which will pull in external
 HTML.  If you don't like H:T, most other templating systems have similar
 features.
 
 And you *should* be using a templating system!  If you've never used one,
 STOP EVERYTHING and go read the POD for HTML::Template, right now!  Don't
 write another line of code before you know how to use it!

I do use HTML::Template. My CGI's usually have three HTML::Template
objects: a header, content, and footer. I realize that each of my
content templates could just TMPL_INCLUDE the header and footer
files, but I choose not to do it that way, for maintenance reasons. When
things change, it can be a big can of worms. I see no reason that my
content templates should have to know anything about the
framework/headers/footers of the site. They should be autonomous,
pluggable anywhere. Isn't that how the rest of the world does it?

I realize that, using my multiple template objects, each of my run-modes
could...

return $app-param('header')-output() .
   $app-param('content')-output() .
   $app-param('footer')-output();

...and I may end up doing just that. It would have the benefit, for
example,