Matt Warnock wrote:
Mason newbie, so please be kind.

Not a chance ;)

I like having a web form and its associated error-checking in the same
file.  Makes it easier if I have to make a design change later.  So I
thought I'd have the form component call itself as its form action.
If in the <%init> section, the $ARGS{submit} value is present, then a
form has been submitted, and we then check for errors.  If not, we
either fetch the needed data to populate the form (for editing an
existing record), or just display the empty form (for inserting a
record).  A separate delete button could be used to delete the record
(after confirmation). All the functions related to that record type in
one file.  Is this a bad idea?  How do Mason experts do this?

It's not a bad approach. In my experience it beats having separate files for each of the insert, edit, view, delete operations.

However, it would be nice to be able to bail out of the <%init> section
early if there is no $ARGS{submit} value, like an early return from a
subroutine, while still executing the rest of the component.  Is there a
way to do that? Or am I asking the wrong question because I am assuming
too much?

Try something like this:

   <%init>
     my $results;
if (my @errors = $m->comp('.validate', %ARGS)) {
       $m->comp('.display_errors', errors => [EMAIL PROTECTED]);
     } elsif ($ARGS{delete}) {
       $results = $m->comp('.delete', %ARGS);
     } elsif ($ARGS{view}) {
       $results = $m->comp('.view', %ARGS);
     } else {
       $results = $m->comp('.default', %ARGS);
     }

     if ($results->{errors}) {
       $m->comp('.display_errors', errors => $results->{errors});
     } else {
       $m->comp('.display_results', %$results);
     }
   </%init>

In this example the init block just serves to shuttle the commands to the appropriate sub-component where most of the the work (business logic) is done. Each sub component does it's own individual error checking and returns the information necessary to build the output to be displayed. The ".display_output" sub-component can then have massive if blocks to construct the appropriate output or it can act as a router to even more sub-components.

Code gets deeply nested if you try to do too much testing this way, and
breaking it into subroutines causes errors every time I try to access
the %ARGS (variable won't stay shared errors) from a perl subroutine.
Outside components defeats the purpose of centralizing the data
references, and inside or sub-components need/get their own %ARGS hash,
I understand.

What I do is have a top level autohandler that puts everything from %ARGS into a global %vars variable. This is accessible from anywhere within HTML::Mason::Commands namespace; subroutines, sub-components, methods, you name it. However, I always recommend staying away from sharing variables and explicitly passing the necessary information as arguments. I only dip into %vars during prototyping and switch to explicit parameter passing as proof of concept is refined into production code.

On a larger scale, how do others manage this stuff where the DBMS is
under active development and you don't want SQL inserts, deletes,
updates, and selects to the same table, with their associated forms and
business logic processes, in many different files all over the place?
What organizing conventions do you find helpful?

A Model View Controller (MVC, google it) architecture is a great way to keep related logic together. Here's a very simplified (read: not pure MVC) example: Say you have a table that holds information about employees. On one page (view) you want to display a list of all of the employees. Here's a list of other possible pages:

   * List of employees in a given department
   * view details of a single employee
   * edit the employee
   * payroll reports that uses employee data
   * projects list with the names of all assigned employees

In an MVC approach you could create a model component* that contains the logic to to run any queries/statements against the database to deal with the various operations performed with employees. This would be accessed by other components by calling component methods that allow you to do what they need.

You could then create a separate view component to represent each of the pages noted above or perhaps a single view component with methods to represent each of them. These components just take complex data structures as their input and generate HTML output. These are the only components that generate any HTML.

Your controller components would be the ones that you see in the url. These are where you put logic for collecting and validating arguments and deciding which model components to call and which view components to call.

As I said this example is very simplified and can barely be considered MVC. Check out Wikipedia for more info on MVC (ignore the parts about leprechauns, that's leftover St. Patrick's Day vandalism) and Google HTML::Mason along with MVC to see how others have come up with more robust approaches.

Have Fun,

-- Ben

* Some would suggest putting this code into a Perl module since it doesn't print any output to the web.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Mason-users mailing list
Mason-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mason-users

Reply via email to