http://qs321.pair.com?node_id=758148

For the simple cases of constraints and value transformations in FormHandler we decided to add Constraints and Filters. For the more complex needs you'll still be allowed to just subclass Field as it used to be, now we just add a way to quickly solve the simple cases.

I've looked at Gerdas latest commit - defining the has_constraint method. Initially I did not like it - as it creates another layer of indirection - but now I think it can nicely fit together with Filters.

Here is my API proposal:

package Test::Form; use HTML::FormHandler::Moose; extends 'HTML::FormHandler'; use DateTime; has_constraint 'contains_aaa' => ( action => qr/aaa/, message => 'Must contain aaa' ); has_constraint 'greater_than_10' => ( action => sub { return $_[0] > + 10 } }, message => 'must be greater than 10' ); has_filter 'eight_leading_zeros' => ( action => sub{ printf("%08d", _[0] ) } ); has_constraint 'only_mondays' => ( action => sub { $_[0]->day_of_week eq 'Monday' }, message => 'Only Mondays' ); has_filter 'date_time' => ( action => sub{ DateTime->new( $_[0] ) }, message => 'Incorrect Date' ); has_field 'some_text' => ( actions => [ 'contains_aaa' ] ); has_field 'number' => ( actions => [ 'greater_than_10', 'eight_leading_zeros' ] ); has_field 'date_time' => ( type => 'Compound', actions => [ 'date_time', 'only_mondays' ], ); has_field 'date_time.year'; has_field 'date_time.month'; has_field 'date_time.day';
So here we have one simple text field that is required to contain the string 'aaa' - this is the simple case. Then we have a number that needs to be greater than 10, but also it is being saved to the database as a string formatted with up to 8 leading zeros. And the most complex one is a DateTime field with three subfields for the year, month and day. It is saved to the database as a DateTime object, and the user is allowed to enter only dates that are Mondays. This example shows how this complex requirement is relatively easily declared using this API. One important note here is that the Compound field assembles the values of the sub-fields into a hash - and that hash is then passed to the filter as the parameter. This should be convenient for all subs with named parameters and in particular to object creators for inflation. And if the inflation fails then the error message is used.

The main point above is that with named filters and constraints the programmer can weave them together in whatever order he needs and is not constrained by the order defined by the library (like in FormFu - where there is a specific order of applying the different actions).

I am not sure about the names - transformations would be more appropriate than filters but also two times longer. Any proposals?

To save some typing (and reading) we also could use positional declarations instead of named:

has_constraint 'contains_aaa' => ( qr/aaa/, 'Must contain aaa' );

Update: The alternative:

package Test::Form; use HTML::FormHandler::Moose; extends 'HTML::FormHandler'; use DateTime; has_field 'some_text' => ( actions => [ { check => qr/aaa/, message => 'Must contain aaa' } ] ); has_field 'number' => ( actions => [ { check => sub { return $_[0] > 10 }, message => 'must be greater than 10' }, { transformation => sub{ printf("%08d", _[0] ) } }, ] ); has_field 'date_time' => ( type => 'Compound', actions => [ { transformation => sub{ DateTime->new( $_[0] ) }, message => 'Incorrect Date' }, { check => sub { $_[0]->day_of_week eq 'Monday' }, message => 'Only Mondays' }, ], ); has_field 'date_time.year'; has_field 'date_time.month'; has_field 'date_time.day';
Shorter - but more identation - which one would you chose?