Form::Tiny::Manual::Compatibility - backward compatibility notice
This documentation page is listing all non-backward compatible changes in usage of Form::Tiny, together with recipes on how to fix them.
Starting from version 2.00, any backward incompatible changes will only be introduced to the module after a 3 month deprecation period. This does not cover bug fixes and changes to internal methods not meant to be used or depended on.
Usually, if the given package / method is documented and the documentation does not state that it is internal, it will not be changed without any notice unless a bug is detected or the change corrects some non-logical behavior.
If a change was made which breaks this policy you are welcome to open an issue in the bugtracker.
fields
Changed in 2.18 - considered mostly backward compatible
Previous versions of Form::Tiny automatically inserted an adjustment for subform fields, which caused the correct behavior of including subform's fields in main form's fields. Overriding the adjust subroutine required explicitly taking fields from the subform.
adjust
This adjustment is no longer injected and correct behavior is achieved internally by the validator. Any forms which used explicit adjustments of subform before should now have a redundant but harmless call to fields, which can be safely removed.
The only scenario in which it breaks backward compatibility is when subform field adjustment did not call fields. In this case, an explicit call to subform's input is required to retain old behavior.
input
Changed in 2.17
Due to new internal structure, Filter has been moved to Plugin directory.
Changed in 2.10
Forms no longer store their validation state in a dedicated field. These methods did nothing starting with version 2.09, and got later removed.
Changed in 2.04
Many parts of the system can be customized with code references (anonymous subroutines). The problem is they were designed in isolation, per feature and not as a whole.
Because of this, parameters they get passed tended to vary. For example the default sub used to get passed a single parameter, which is a form instance, while form validator would not get passed a form instance, making it hard or impossible to make use of instance data in certain places.
default
To combat this, all listed places now consistently get passed the form instance as their first parameter, followed by their former parameters:
form_field -> adjust form_field -> coerce form_validator form_filter field_filter
For example:
form_field 'field' => ( # before adjust => sub { shift() + 1 }, # after adjust => sub { $_[1] + 1 }, );
Or with signatures:
form_field 'field' => ( # before adjust => sub ($value) { $value + 1 }, # after adjust => sub ($self, $value) { $value + 1 }, );
Use Form::Tiny::Error::Required instead.
# Old form field_filter 'field_name', Type, sub { ... }; # New form - use context instead form_field 'field_name'; field_filter Type, sub { ... };
# Old form field_filter Form::Tiny::Filter->new( field => 'field_name', type => Type, code => sub { ... }, ); # New form - use context instead form_field 'field_name'; field_filter Form::Tiny::Filter->new( type => Type, code => sub { ... }, );
Changed in 2.01 - considered bugfix
In previous versions, the validation process started off by deep cloning the input by calling Storable::dclone on it. It was unnecessary and had the potential to lead to subtle bugs.
Storable::dclone
The validation process is cloning most of the input by itself by mangling fields and then putting them back in the result hashref, much alike the input one, but completely separate. However, if you specify that a field should be an object of certain type, that will not get cloned. Same for explicit array and hash references (not those specified as a path, like key1.key2). Removing deep cloning fixed that, as those would get cloned anyway.
key1.key2
So now, if you specify your field to contain something that is not a reference, it will get cloned. If you specify something that is a reference, it will not get cloned, and changing it will also change that single key in the input hash. You have all the power to decide.
If you still want to deep clone your input data you can use the reformat hook for that. See "Hooks" in Form::Tiny::Manual.
reformat
Changed in 2.00
In the past, declaring a form as filtered caused it to trim strings before validation by default.
This behavior was removed due to difficulty in designing a sane interface that would allow opting out of it. An exception of inline forms (Form::Tiny::Inline) was introduced, which still trim by default when declared to be capable of filtering.
As this behavior is often needed, a keyword was introduced that allows to enable it in a form:
use Form::Tiny -filtered; form_trim_strings;
In version 2.00 a field definition which is built by a subroutine is called a dynamic field, since it cannot be resolved in the form metaclass due to access to form object as its first argument. Due to changes on where the field definitions are stored, these subroutines are no longer ran once for each form object, but rather multiple times, possibly even during a single validation process.
This behavior is more correct, as class fields which you can access might change between validations, and old field building would not take it into account. However, it also means that subroutines that build form fields must not to contain any form of non-determinism (like random number generation) or (to less degree) something variable in time (like datetime or access to busy database entries).
Minor change in 2.03
As of 2.03, the field definitions are still resolved dynamically, but will keep their state until you trigger form reset by changing the input (with set_input method). This allows for some degree of randomness in forms, but it will still change after you set different input. If you really want randomness that will last for the entire lifetime of an object, regular class attribute accessed in a dynamic field is your best bet:
set_input
has 'random_field' => ( is => 'ro', default => sub { rand }, ); form_field sub { my $self = shift; # access with $self->random_field; };
Previously, this syntax was allowed:
form_field 'my_field' => sub { return { type => Int, }; };
Due to changes on how form_field handles its arguments and how fields are resolved, this now only accepts a subroutine reference, which in turn has to return name explicitly:
form_field sub { return { name => 'my_field', type => Int, }; };
Previously, hooks were just a primitive system based on method overriding:
sub pre_validate { my ($self, $data) = @_; ...; # actual hook code return $data; }
This system was hard to handle and often buggy due to roles not copying methods over rather than actual method resolution. It was replaced by a new, much more powerful system:
form_hook before_validate => sub { my ($self, $data) = @_; ...; # actual hook code return $data; };
In the process, pre word in hooks names became before, multiple hooks became possible, and new hooks were added.
pre
before
Previously, backslash \ could only be used in field names before the dot . to avoid its meaning of nesting operator. There was no way to escape a star * to have it as a literal hash key name rather than meaning an array.
\
.
*
It has been changed so that backslash escapes every special character in field names. This means that a backslash must be escaped by another backslash to have a literal backslash:
form_field '\\.'; # a literal dot form_field '\\\\.'; # syntax error - a literal backslash followed by a nesting separator form_field '\\\\\\.'; # a literal backslash followed by a literal dot
In the past, it was possible to define a form by defining three methods in the package: build_fields, build_cleaner and build_filters. This was a part of the initial implementation and was later scraped when form metaobject was introduced.
build_fields
build_cleaner
build_filters
If you happened to use the module during its early days, you must adjust your code to the new DSL style. It should not require drastic changes, but rather moving declarations out from class methods to DSL keywords. Refer to "Form domain-specific language" in Form::Tiny for details.
None at this time.
Form::Tiny::Manual
To install Form::Tiny, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Form::Tiny
CPAN shell
perl -MCPAN -e shell install Form::Tiny
For more information on module installation, please visit the detailed CPAN module installation guide.