[Html-widget] formfu validation proposals

Brian Kirkbride brian.kirkbride at deeperbydesign.com
Thu Mar 8 18:50:12 GMT 2007


Carl Franks wrote:
> The old HTML-Widget process() simply ran all constraints, then all
> filters, and that was your lot.
> 
> FormFu currently goes a step further with:
>  * constraints
>  * filters
>  * inflators
> 
> I propose making it a lot more powerful and flexible, with the following 
> steps:
>  * filter
>  * constrain
>  * inflate
>  * validate
>  * transform
> 
> Any of these steps (except 'filter') will be able to throw an
> exception, which will be displayed to the user as a field error.
> Each step will only proceed if there are no errors from previous steps.
> 
> The first filter for each field will be fed the raw input for that
> field only, and it's output will be piped to the next filter for that
> field.
> Likewise, with 'inflate', the output is piped from one inflate handler
> to the next.
> The same goes for 'transform', but the first transform handler will
> receive the inflated value.
> 
> The purpose of the filter handlers would be to cleanup input before
> validation, so you might strip leading and trailing whitespace with
> the 'TrimEdges' filter. Or you might use the 'NonNumeric' filter to
> remove any spaces or hyphens entered into a credit card number field.
> 
> The purpose of the 'constrain' handlers would be to check such
> low-level things such as "is this in range?", "does this contain valid
> characters?" or "is this an email address?".
> 
> The purpose of the 'inflate' handlers would be to, for example, turn a
> date into a DateTime object, or turn a file upload into an Imager
> object.
> 
> The purpose of the 'validate' handlers would be to check higher-level
> (business) rules, and they will have access to the inflated values of
> all fields. So you could check, for example, "is this date after that
> date?" or "is 'c' only filled in if 'a' and 'b' are?".
> 
> Because these are likely to contain more-complex logic, it would be
> expected that the user would create a new subclass of
> HTML::Widget::Validate for each business rule, which would contain the
> programmatic logic. So in your form setup, you only need refer to the
> validation handler by name (otherwise, you'd end up trying to program
> in yaml - nasty!).
> 
> And, of course, if you're using Catalyst::Controller::HTML::FormFu,
> your validation code will have access to the catalyst context via the
> form's stash.
>    $self->form->stash->{context}
> 
> The 'transform' handler is provided as a further hook to do anything
> else necessary after all validation is complete.
> 
> You might notice each of these steps are a verb name. This would allow
> me to get rid of the 'plural' aliases filter/filters,
> constraint/contraints, which I don't like for some reason ;)
> 
> So, to take the example of John Napiorkowski's HTML-Widget filters
> which use Imager to resize uploaded image files to a standard size...
> 
> I would suggest there should be a HTML::FormFu::Inflate::Imager which
> simply reads an uploaded file and returns an Imager object.
> There would then be a HTML::FormFu::Transform::Imager which allows you
> to call methods on that Imager object.
> The yaml config for a field might be something like:
> 
> ---
> element:
>  - type: file
>    name: avatar
>    inflate:
>      - Imager
>    transform:
>      - type: Imager
>        scaleX: [pixels, 100]
> 
> Any ideas / criticisms?
> 
> Cheers,
> Carl
> 

This sounds fantastic Carl!

My thinking has been to separate the syntax (constraint) and semantic 
(validation) checking in my form handlers lately.  This fits right in line with 
that.

Some quick questions:

Should each inflate operation return the new object or stick it in the stash, 
returning something of the same type as it got?  Probably it should pass it 
along as you have described, but this means you'd have to consider the order and 
effects of each inflator.  Though that is most likely what you would want, so...

How do you envision the exception handling to work?
- die()-ing with $@ going into the error message for the field
- die()-ing with some indicator that the exception was not a runtime error but a 
constraint failure, etc
- setting something in the stash and returning undef

All in all, this looks like quite an improvement in flexibility and separation 
of concerns.  The latter is such a problem in form handling!

Best,
Brian Kirkbride



More information about the Html-widget mailing list