Subject: | msgs lookup doesn't work for built in closures |
Hello,
I've run into an issue with msgs not working for built in constraint closures.
Basically, when using 'use Data::FormValidator::Constraints qw( email );' then defining a msgs
contraints message for parameter using with name '$results->msgs->{name}' will return
default string.
It appears that the constraint name is being set to the stringification of the code reference
instead of using 'name'.
I've attached a test case and patch for this issue. I had trouble finding the root of why this
was being set. My patch is a work around for when the closures are setup. It seems that root
cause is in the 'Data::FormValidator::Results::_constraint_hash_build' sub but my few attempts
at fixing it seem to not have worked and the code is probably best updated by someone that
is more familiar w/ all of the logic.
My current workaround is to replicate the constraint closure in my local code.
Thanks,
Lee
Subject: | Constraints.pm.diff |
*** lib/Data/FormValidator/Constraints.pm 2011-12-13 09:27:41.000000000 -0600
--- ../orig.Data-FormValidator-4.70/lib/Data/FormValidator/Constraints.pm 2011-11-11 21:10:29.000000000 -0600
***************
*** 60,67 ****
die "first arg to $func was not an object. Must be called as a constraint_method."
unless ( Scalar::Util::blessed(\$dfv) && \$dfv->can('name_this') );
! \$dfv->name_this('$func') unless \$dfv->get_current_constraint_name()
! && \$dfv->get_current_constraint_name() \!~ m\/^CODE\\(\\w+\\)\$\/;
no strict 'refs';
return &{"match_$func"}(\@_);
}
--- 60,66 ----
die "first arg to $func was not an object. Must be called as a constraint_method."
unless ( Scalar::Util::blessed(\$dfv) && \$dfv->can('name_this') );
! \$dfv->name_this('$func') unless \$dfv->get_current_constraint_name();
no strict 'refs';
return &{"match_$func"}(\@_);
}
Subject: | closure_msgs.t |
use Test::More qw/no_plan/;
use strict;
use Data::FormValidator;
use Data::FormValidator::Constraints qw( email );
my $cm_profile = {
required => [qw( admin prefork )],
constraint_methods => {
admin => email(),
prefork => my_email()
},
msgs => {
missing => 'Test-Missing',
invalid => 'Test-Invalid',
invalid_seperator => ' ## ',
constraints => {
admin => 'Invalid Email Address',
email => 'Invalid Email Address'
},
format => 'ERROR: %s',
prefix => 'error_',
}
};
my $validator = new Data::FormValidator( { cm => $cm_profile } );
my $input_hashref =
{ admin => 'invalidemail', prefork => 9, sleep => 11, rounds => 8 };
my $results;
TODO: {
local $TODO = 'need to test for msgs() called before validate';
# msgs() should return emit a warning and return undef if the hash
# structure it points to is undefined. However, if it points to an
# empty hash, then maybe there are just no messages.
}
# testing simple msg definition, $self->msgs should be returned as a hash ref
my $msgs;
# check constraint msg when using 'email' closure
eval { $results = $validator->check( $input_hashref, 'cm' ); };
is $@, '', 'survived eval';
$msgs = $results->msgs;
like $msgs->{error_admin}, qr/Invalid Email Address/,
'custom message (built in closure)';
like $msgs->{error_prefork}, qr/Invalid Email Address/,
'custom message (local closure)';
exit;
# provide locally defined closure constraint method
sub my_email {
return sub {
my $dfv = shift;
# Name it to refer to in the 'msgs' system.
$dfv->name_this('email');
# value of 'prospective_date' parameter
my $in_email = $dfv->get_current_constraint_value();
# get other data to refer to
my $data = $dfv->get_filtered_data;
require Email::Valid;
my $valid_email;
# The extra check that the result matches the input prevents
# an address like this from being considered valid: Joe Smith <joe@smith.com>
if ( ( $valid_email = Email::Valid->address($in_email) )
and ( $valid_email eq $in_email ) )
{
return $valid_email;
}
else {
return undef;
}
}
}