Validate: Rename "scalar" to "accept_scalar" and add "accept_array"
This commit is contained in:
parent
f8fe53cba9
commit
3382deba9a
2 changed files with 33 additions and 10 deletions
|
|
@ -13,7 +13,8 @@ my %builtin = map +($_,1), qw/
|
||||||
default
|
default
|
||||||
onerror
|
onerror
|
||||||
trim
|
trim
|
||||||
elems scalar sort unique
|
elems sort unique
|
||||||
|
accept_scalar accept_array
|
||||||
keys values unknown missing
|
keys values unknown missing
|
||||||
func
|
func
|
||||||
/;
|
/;
|
||||||
|
|
@ -22,8 +23,9 @@ my %type_vals = map +($_,1), qw/scalar hash array any/;
|
||||||
my %unknown_vals = map +($_,1), qw/remove reject pass/;
|
my %unknown_vals = map +($_,1), qw/remove reject pass/;
|
||||||
my %missing_vals = map +($_,1), qw/create reject ignore/;
|
my %missing_vals = map +($_,1), qw/create reject ignore/;
|
||||||
my %implied_type = qw/
|
my %implied_type = qw/
|
||||||
|
accept_array scalar
|
||||||
keys hash values hash unknown hash
|
keys hash values hash unknown hash
|
||||||
elems array sort array unique array scalar array
|
elems array sort array unique array accept_scalar array
|
||||||
/;
|
/;
|
||||||
my %sort_vals = (
|
my %sort_vals = (
|
||||||
str => sub($x,$y) { $x cmp $y },
|
str => sub($x,$y) { $x cmp $y },
|
||||||
|
|
@ -151,6 +153,7 @@ sub _compile($schema, $custom, $rec, $top, $validations=$top->{validations}) {
|
||||||
if ($builtin{$name}) {
|
if ($builtin{$name}) {
|
||||||
confess "Invalid value for 'missing': $val" if $name eq 'missing' && !$missing_vals{$val};
|
confess "Invalid value for 'missing': $val" if $name eq 'missing' && !$missing_vals{$val};
|
||||||
confess "Invalid value for 'unknown': $val" if $name eq 'unknown' && !$unknown_vals{$val};
|
confess "Invalid value for 'unknown': $val" if $name eq 'unknown' && !$unknown_vals{$val};
|
||||||
|
confess "Invalid value for 'accept_array': $val" if $name eq 'accept_array' && $val && $val ne 'first' && $val ne 'last';
|
||||||
$val = $sort_vals{$val} || confess "Unknown value for 'sort': $val" if $name eq 'sort' && ref $val ne 'CODE';
|
$val = $sort_vals{$val} || confess "Unknown value for 'sort': $val" if $name eq 'sort' && ref $val ne 'CODE';
|
||||||
$top->{$name} = $val;
|
$top->{$name} = $val;
|
||||||
next;
|
next;
|
||||||
|
|
@ -273,6 +276,10 @@ sub _validate_input {
|
||||||
|
|
||||||
my $type = $c->{type} // 'scalar';
|
my $type = $c->{type} // 'scalar';
|
||||||
|
|
||||||
|
# accept_array (needs to be done before 'trim')
|
||||||
|
$_[1] = $_[1]->@* == 0 ? undef : $c->{accept_array} eq 'first' ? $_[1][0] : $_[1][ $#{$_[1]} ]
|
||||||
|
if $c->{accept_array} && ref $_[1] eq 'ARRAY';
|
||||||
|
|
||||||
# trim (needs to be done before the 'default' test)
|
# trim (needs to be done before the 'default' test)
|
||||||
$_[1] = trim $_[1] =~ s/\r//rg if defined $_[1] && !ref $_[1] && $type eq 'scalar' && (!exists $c->{trim} || $c->{trim});
|
$_[1] = trim $_[1] =~ s/\r//rg if defined $_[1] && !ref $_[1] && $type eq 'scalar' && (!exists $c->{trim} || $c->{trim});
|
||||||
|
|
||||||
|
|
@ -305,8 +312,8 @@ sub _validate_input {
|
||||||
}
|
}
|
||||||
|
|
||||||
} elsif ($type eq 'array') {
|
} elsif ($type eq 'array') {
|
||||||
$_[1] = [$_[1]] if $c->{scalar} && !ref $_[1];
|
$_[1] = [$_[1]] if $c->{accept_scalar} && !ref $_[1];
|
||||||
return { validation => 'type', expected => $c->{scalar} ? 'array or scalar' : 'array', got => lc ref $_[1] || 'scalar' } if ref $_[1] ne 'ARRAY';
|
return { validation => 'type', expected => $c->{accept_scalar} ? 'array or scalar' : 'array', got => lc ref $_[1] || 'scalar' } if ref $_[1] ne 'ARRAY';
|
||||||
$_[1] = [$_[1]->@*]; # Create a shallow copy to prevent in-place modification.
|
$_[1] = [$_[1]->@*]; # Create a shallow copy to prevent in-place modification.
|
||||||
|
|
||||||
} elsif ($type eq 'any') {
|
} elsif ($type eq 'any') {
|
||||||
|
|
@ -600,10 +607,10 @@ Failure is reported in a similar fashion to I<keys>:
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
=item scalar => 0/1
|
=item accept_scalar => 0/1
|
||||||
|
|
||||||
Implies C<< type => 'array' >>, this option will also permit the input to be a
|
Implies C<< type => 'array' >>, this option will also permit the input to be a
|
||||||
scalar. In this case, the input is interpreted and returned as an array with
|
scalar. In that case, the input is interpreted and returned as an array with
|
||||||
only one element. This option exists to make it easy to validate multi-value
|
only one element. This option exists to make it easy to validate multi-value
|
||||||
form inputs. For example, consider C<query_decode()> in L<FU::Util>: a
|
form inputs. For example, consider C<query_decode()> in L<FU::Util>: a
|
||||||
parameter in a query string is decoded into an array if it is listed multiple
|
parameter in a query string is decoded into an array if it is listed multiple
|
||||||
|
|
@ -613,16 +620,24 @@ times, a scalar if it only occcurs once. So we could either end up with:
|
||||||
# OR:
|
# OR:
|
||||||
{ a => [1, 3], b => 1 }
|
{ a => [1, 3], b => 1 }
|
||||||
|
|
||||||
With the I<scalar> option, we can accept both forms for C<a> and normalize into
|
With the I<accept_scalar> option, we can accept both forms for C<a> and
|
||||||
an array. The following schema definition can validate the above examples:
|
normalize into an array. The following schema definition can validate the above
|
||||||
|
examples:
|
||||||
|
|
||||||
{ type => 'hash',
|
{ type => 'hash',
|
||||||
keys => {
|
keys => {
|
||||||
a => { type => 'array', scalar => 1 },
|
a => { type => 'array', accept_scalar => 1 },
|
||||||
b => { }
|
b => { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=item accept_array => false/'first'/'last'
|
||||||
|
|
||||||
|
Implies C<< type => 'scalar' >>. Similar to I<accept_scalar> but normalizes in
|
||||||
|
the other direction: when the input is an array, only the first or last item is
|
||||||
|
extracted and the other elements are ignored. If the input is an empty array,
|
||||||
|
the value is taken to be C<undef>.
|
||||||
|
|
||||||
=item sort => $option
|
=item sort => $option
|
||||||
|
|
||||||
Implies C<< type => 'array' >>, sort the array after validating its elements.
|
Implies C<< type => 'array' >>, sort the array after validating its elements.
|
||||||
|
|
|
||||||
10
t/validate.t
10
t/validate.t
|
|
@ -79,12 +79,20 @@ t { trim => 0 }, " Va\rl id \n ", " Va\rl id \n ";
|
||||||
f {}, ' ', { validation => 'required' }, 'required value missing';
|
f {}, ' ', { validation => 'required' }, 'required value missing';
|
||||||
t { trim => 0 }, ' ', ' ';
|
t { trim => 0 }, ' ', ' ';
|
||||||
|
|
||||||
|
# accept_array
|
||||||
|
t { default => undef, accept_array => 'first' }, [], undef;
|
||||||
|
t { default => undef, accept_array => 'first' }, [' x '], 'x';
|
||||||
|
t { accept_array => 'first' }, [1,2,3], 1;
|
||||||
|
t { accept_array => 'last' }, [1,2,3], 3;
|
||||||
|
f { accept_array => 'first' }, [' ', 1], { validation => 'required' }, 'required value missing';
|
||||||
|
f { accept_array => 'first' }, [], { validation => 'required' }, 'required value missing';
|
||||||
|
|
||||||
# arrays
|
# arrays
|
||||||
f {}, [], { validation => 'type', expected => 'scalar', got => 'array' }, "invalid type, expected 'scalar' but got 'array'";
|
f {}, [], { validation => 'type', expected => 'scalar', got => 'array' }, "invalid type, expected 'scalar' but got 'array'";
|
||||||
f { type => 'array' }, 1, { validation => 'type', expected => 'array', got => 'scalar' }, "invalid type, expected 'array' but got 'scalar'";
|
f { type => 'array' }, 1, { validation => 'type', expected => 'array', got => 'scalar' }, "invalid type, expected 'array' but got 'scalar'";
|
||||||
t { type => 'array' }, [], [];
|
t { type => 'array' }, [], [];
|
||||||
t { type => 'array' }, [undef,1,2,{}], [undef,1,2,{}];
|
t { type => 'array' }, [undef,1,2,{}], [undef,1,2,{}];
|
||||||
t { type => 'array', scalar => 1 }, 1, [1];
|
t { type => 'array', accept_scalar => 1 }, 1, [1];
|
||||||
f { type => 'array', elems => {} }, [undef], { validation => 'elems', errors => [{ index => 0, validation => 'required' }] }, "[0]: required value missing";
|
f { type => 'array', elems => {} }, [undef], { validation => 'elems', errors => [{ index => 0, validation => 'required' }] }, "[0]: required value missing";
|
||||||
t { type => 'array', elems => {} }, [' a '], ['a'];
|
t { type => 'array', elems => {} }, [' a '], ['a'];
|
||||||
t { type => 'array', sort => 'str' }, [qw/20 100 3/], [qw/100 20 3/];
|
t { type => 'array', sort => 'str' }, [qw/20 100 3/], [qw/100 20 3/];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue