[Dancer-users] Input-validation and Error-Handling in a fun 'dancer' way

Brian E. Lozier brian at massassi.com
Wed Sep 14 22:21:55 CEST 2011


On Wed, Sep 14, 2011 at 12:55 PM, Octavian Rasnita <orasnita at gmail.com>wrote:

> HTML::FormFu can verify very easy if the submitted form would create a
> dupplicate in the database, using a custom Validator.
>

Sure, but you will always end up with a possible race-condition, especially
on high-traffic sites.  Between the time you check for a row with a
duplicate key and actually try to insert a record could have been inserted.
Anyway, it was only an example.  There are other things that can cause a
form submission to fail other than invalid input or duplicate key issues.
If your form handler is talking to an external web service, for example, and
the service is unavailable, or if you're trying to copy an uploaded file to
a filesystem that has no space on it, etc.



> Such a validator could look like the one below.
> I created it under the HTML::FormFu namespace, but it can be created under
> application's namespace
>
> It is done for a Catalyst-based app, so the line:
>  my $c = $self->form->stash->{context};
> just gets the context object $c from the form's stash, because it needs to
> access the DBIC model that searches in the database if the value of the
> field ($value, which is also found in the $fields hashref) is unique in the
> database.
> The DBIC method unique_community_name just searches if it is unique, and it
> returns just true/false.
>
> And the HTML::FormFu may print a custom message defined with the key
> "message" for this Validator, so it is all very clean, and you may use the
> unique_community_name method to do the searches for uniqueness for other
> things, and you may also use this validator for other forms.
> (Too tired right now, so my explanations might not be very clear:)
>
>
> package HTML::FormFu::Validator::BRK::UniqueCommunityNameAdd;
>
> use strict;
> use warnings;
> use parent 'HTML::FormFu::Validator';
>
> sub validate_value {
>  my ($self, $value, $params) = @_;
>  my $c = $self->form->stash->{context};
>  return $c->model("DB::Usr")->unique_community_name_add($params);
> }
>
> 1;
>
>
> Octavian
>
> ----- Original Message -----
> From: "Brian E. Lozier" <brian at massassi.com>
> To: "Assaf Gordon" <gordon at cshl.edu>
> Cc: <dancer-users at perldancer.org>
> Sent: Wednesday, September 14, 2011 9:22 PM
> Subject: Re: [Dancer-users] Input-validation and Error-Handling in a fun
> 'dancer' way
>
>
> > On Wed, Sep 14, 2011 at 11:12 AM, Assaf Gordon <gordon at cshl.edu> wrote:
> >
> >> Hello Dancers,
> >>
> >> I have another dancer-newbie question:
> >>
> >> Is there a recommended way to verify input (or general variables) and
> >> report errors to the user ?
> >>
> >
> > Hello,
> >
> > I use a combination of HTML::FormFu and Dancer::Plugin::FlashMessage for
> > this purpose.  HTML::FormFu has built-in ways to validate data and report
> > input errors back to the user.  This isn't quite enough because even
> though
> > the input can be perfectly valid, there are times when something during
> form
> > processing will fail (for example, a database duplicate key). In those
> cases
> > I use the FlashMessage to report it to the user.  There are numerous
> > advantages to using HTML::FormFu or some other form handling library.
> > First, they provide a framework for doing form validation so you don't
> have
> > to manually code it for each form. Second, they provide a way to
> > structure/define your forms so they can be reused (or inherited from) in
> > other places.  Third, they provide feedback for invalid fields right by
> the
> > fields.  Fourth, they leverage a ton of work that other developers have
> put
> > into solving the same problem.  There are countless more.
> >
> > No, HTML::FormFu isn't perfect but I've found it to be a time saver in
> the
> > long run, even after just a couple of forms.
> >
> > What I do is define the route to accept GET and POST.  Then I create an
> > HTML::FormFu object.  I use the HTML::FormFu mechanism for detecting
> whether
> > the form was submitted.  If the form was submitted and is valid, I
> process
> > it and redirect the user to a confirmation page (with a friendly
> message).
> > If the form was not submitted or was not valid, I just return the
> template,
> > passing the form object in for rendering.  HTML::FormFu takes care of
> > outputting the raw form or possibly with error messages interpolated if
> the
> > input was invalid.
> >
> >
> >>
> >> Common scenario:
> >> I have a form with 3 inputs, and they need to by in a certain format
> >> (verifiable by a simple regex).
> >> If the inputs do not conform, I want to:
> >>
> >> 1. Log the error for later inspection
> >> 2. Inform the user (e.g. using Plugin::Dancer::FlashMessage)
> >> (The error message reported to the user is not necessarily the same one
> >> written to the log, if I wish to include more technical details in the
> log,
> >> or be more descriptive and verbose to the user).
> >> 3. Stop processing the request.
> >>
> >> And I wish to do it in the most 'fun' dancer kind of way.
> >>
> >> Looking at a naive implementation (below), there's alot of redundant
> code
> >> for validating and reporting the error back to the user (and more
> validation
> >> code than actual processing code).
> >>
> >> Any suggestions ?
> >>
> >> Thanks!
> >>  -gordon
> >>
> >>
> >> ====================
> >>
> >> post '/dosomething' => sub {
> >>    my $email = params->{email};
> >>    my $gene = params->{gene};
> >>    my $cutoff = param->{cutoff};
> >>
> >>     if (!defined $email) {
> >>        warning "Missing email address";
> >>        flash error => 'Missing email address';
> >>        return template 'form_errors' ;
> >>    }
> >>    elsif (!valid_email($email)) {
> >>        warning "Got Invalid email address: $email";
> >>        flash error => 'Invalid email address";
> >>        return template 'form_errors' ;
> >>    }
> >>
> >>    if (!defined $gene) {
> >>        warning "Missing gene identifier";
> >>        flash error => 'Missing gene identifier';
> >>        return template 'form_errors' ;
> >>    }
> >>    elsif (!valid_gene_identifier($gene)) {
> >>        warning "Got Invalid gene identifier: $gene";
> >>        flash error => 'Invalid gene identifier";
> >>        return template 'form_errors' ;
> >>    }
> >>
> >>    if (!defined $cutoff) {
> >>        warning "Missing cutoff identifier";
> >>        flash error => 'Missing cutoff identifier';
> >>        return template 'form_errors' ;
> >>    }
> >>    elsif (!valid_cutoff_value($cutoff)) {
> >>        warning "Got Invalid cutoff value: $cutoff";
> >>        flash error => 'Invalid Cutoff value: must a value between 0.1
> and
> >> 0.55';
> >>        return template 'form_errors' ;
> >>    }
> >>
> >>    ## Input IS OK, do some processing and return the result
> >>    my ($result, $error) = process($email, $gene, $cutoff);
> >>
> >>    template 'result.tt', {
> >>          email => $email,
> >>          cutoff => $cutoff,
> >>          gene  => $gene,
> >>          result => $result,
> >>          error => $error,
> >>    };
> >> }
> >> _______________________________________________
> >> Dancer-users mailing list
> >> Dancer-users at perldancer.org
> >> http://www.backup-manager.org/cgi-bin/listinfo/dancer-users
> >>
> >
>
>
>
> --------------------------------------------------------------------------------
>
>
> > _______________________________________________
> > Dancer-users mailing list
> > Dancer-users at perldancer.org
> > http://www.backup-manager.org/cgi-bin/listinfo/dancer-users
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.backup-manager.org/pipermail/dancer-users/attachments/20110914/d59f8cd4/attachment-0001.htm>


More information about the Dancer-users mailing list