Re: Data validation

[prev] [thread] [next] [Date index for 2004/11/10]

From: Drew Taylor
Subject: Re: Data validation
Date: 14:56 on 10 Nov 2004
On Tue, 9 Nov 2004 17:40:40 -0800, Dan Sully <daniel@xxxxxxxxxxxx.xxx> wrote:
> * Drew Taylor <taylor.andrew.j@xxxxx.xxx> shaped the electrons to say...
> 
> >I also follow the MVC pattern in my applications. I do form validation
> >in my CGI::Application-based applications with DFV, but the paranoid
> >part of me wants validation at the model level too - mostly to check
> >for required fields, etc.
> 
> Is anyone using DFV with mod_perl + Template Toolkit? I'd love to see some examples.

This probably isn't anything special but here's how I'm currently
doing it. This uses a combination of CGI::App::Plugin::TT and DFV.
First my form display and processing code is in separate methods. The
display methods can be named anything (set via run_modes() in
setup()), and the processing methods are name "process_$rm" where $rm
is the current runmode. So in prerun I check to see if the form has
been submitted (I just use a hidden element). If not, then continue
running the display method.

If it was submitted, check to see if a DFV profile has been defined. I
have this in another method called "profile_$rm" where $rm is the
current runmode and just returns a data structure suitable for use
with DFV. If no profile was defined, go ahead and run the processing
code assuming that it does whatever validation it needs. If uses the
prerun_mode() method to change the runmode. Remember that you are
changing the runmode if any code/templates need this. It's as simple
as $rm =~ s/^process_//;

If a DFV profile was defined, then run DFV using that profile. If
there are any errors, store them for later inclusion into the template
params and DON'T run the processing code. If everything passes, change
the runmode via prerun_mode() and run the processing method. This
assumes that the processing will either return a redirect (what I
typically do to avoid form resubmission problems), or  output
something.

I'm sure someone will say "That's rather complicated. Why not just go
ahead and define a procesing runmode and have the form submit to that
runmode directly?" This is really a matter of my personal preference.
I don't want the processing code to be directly accessible via a
runmode. In my scheme, it's added on the fly via run_modes() as
needed. All my processing method redirect back to a display runmode
after doing their thing, so I only want them run when the
circumstances are right.

For me, this makes it very easy to write new runmodes: I write a
display method, a processing method, and a validation method. The
decision about when to call each is done automatically, and I get data
validation for minimal effort. The only big thing left on my todo list
is a way to get the templates (TT of course) to automatically include
the error messages - "[% err_element_name %] beside the form elements.
The code below was written by me, for me, and anyone is free to resuse
as much as you like.

Comments welcome!

Drew

sub cgiapp_prerun {
    my $self = shift;

    my $rm = $self->get_current_runmode;

    # check for form submission
    if (!$self->is_form_submitted) {
	return;
    }

    # check for method defining DFV profile - not required
    my $profile_method = "_profile_$rm";
    unless ($self->can($profile_method)) {
	$self->_set_processing_mode($rm);
	return;
    }

    # get the profile data structure - required at this point
    my $profile;
    eval {
	$profile = $self->$profile_method();
    };
    $self->prerun_mode('error', $@) if $@ || !$profile;

    # check the profile and save any errors
    my $dfv = Data::FormValidator->new({}, $self->dfv_defaults);
    my $results = $dfv->check($self->query, $profile);
    if ($results->has_missing || $results->has_invalid) {
	$self->param('dfv_results', $results);
	my $msgs = $results->msgs;
	$self->param('dfv_msgs', $msgs);
	$self->status("Error processing the form");
	return;
    }

    $self->_set_processing_mode($rm);
}

sub _set_processing_mode {
    my ($self, $rm) = @_;

    # run the processor method
    $rm = "process_$rm";
    $self->run_modes($rm => $rm);
    $self->prerun_mode($rm);
}

        -- 
        ----------------------------------------------------------------
 Drew Taylor                 *  Web development & consulting
 Email: drew@xxxxxxxxxx.xxx  *  Site implementation & hosting
 Web  : www.drewtaylor.com   *  perl/mod_perl/DBI/mysql/postgres
 ----------------------------------------------------------------

(message missing)

Data validation
Drew Taylor 20:39 on 09 Nov 2004

Re: Data validation
Drew Taylor 20:44 on 09 Nov 2004

Re: Data validation
Perrin Harkins 22:08 on 09 Nov 2004

Re: Data validation
Drew Taylor 22:14 on 09 Nov 2004

Re: Data validation
Edward J. Sabol 23:20 on 09 Nov 2004

Re: Data validation
Drew Taylor 01:15 on 10 Nov 2004

Re: Data validation
Dan Sully 01:40 on 10 Nov 2004

Re: Data validation
Perrin Harkins 06:42 on 10 Nov 2004

Re: Data validation
Dan Sully 06:59 on 10 Nov 2004

Re: Data validation
Drew Taylor 14:56 on 10 Nov 2004

Re: Data validation
Drew Taylor 15:03 on 10 Nov 2004

Re: Data validation
Perrin Harkins 22:03 on 10 Nov 2004

Re: Data validation
Kingsley Kerce 14:38 on 10 Nov 2004

Re: Data validation
Drew Taylor 15:17 on 10 Nov 2004

Re: Data validation
Tony Bowden 19:28 on 10 Nov 2004

Re: Data validation
Perrin Harkins 21:20 on 10 Nov 2004

Re: Data validation
Cees Hek 23:52 on 10 Nov 2004

Generated at 11:34 on 01 Dec 2004 by mariachi v0.52