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