my $cache_key = _cache_key( \%spec );
+ my $allow_extra = delete $spec{MX_PARAMS_VALIDATE_ALLOW_EXTRA};
+
if ( exists $CACHED_SPECS{$cache_key} ) {
( ref $CACHED_SPECS{$cache_key} eq 'HASH' )
|| confess
for grep { $spec{$_}{coerce} && exists $args{$_} } keys %spec;
%args = Params::Validate::validate_with(
- params => \%args,
- spec => \%spec,
- called => _caller_name(),
+ params => \%args,
+ spec => \%spec,
+ allow_extra => $allow_extra,
+ called => _caller_name(),
);
return ( ( defined $instance ? $instance : () ), %args );
my $cache_key = _cache_key( \%spec );
+ my $allow_extra = delete $spec{MX_PARAMS_VALIDATE_ALLOW_EXTRA};
+
my @ordered_spec;
if ( exists $CACHED_SPECS{$cache_key} ) {
( ref $CACHED_SPECS{$cache_key} eq 'ARRAY' )
for grep { $spec{$_}{coerce} && exists $args{$_} } keys %spec;
%args = Params::Validate::validate_with(
- params => \%args,
- spec => \%spec,
- called => _caller_name(),
+ params => \%args,
+ spec => \%spec,
+ allow_extra => $allow_extra,
+ called => _caller_name(),
);
return (
my $cache_key = _cache_key( \%extra );
+ my $allow_extra = delete $extra{MX_PARAMS_VALIDATE_ALLOW_EXTRA};
+
my @pv_spec;
if ( exists $CACHED_SPECS{$cache_key} ) {
( ref $CACHED_SPECS{$cache_key} eq 'ARRAY' )
for grep { $pv_spec[$_] && $pv_spec[$_]{coerce} } 0 .. $#args;
@args = Params::Validate::validate_with(
- params => \@args,
- spec => \@pv_spec,
- called => _caller_name(),
+ params => \@args,
+ spec => \@pv_spec,
+ allow_extra => $allow_extra,
+ called => _caller_name(),
);
return @args;
=back
+=head1 ALLOWING EXTRA PARAMETERS
+
+By default, any parameters not mentioned in the parameter spec cause this
+module to throw an error. However, you can have have this module simply ignore
+them by setting C<MX_PARAMS_VALIDATE_ALLOW_EXTRA> to a true value when calling
+a validation subroutine.
+
+When calling C<validated_hash> or C<pos_validated_list> the extra parameters
+are simply returned in the hash or list as appropriate. However, when you call
+C<validated_list> the extra parameters will not be returned at all. You can
+get them by looking at the original value of C<@_>.
+
=head1 EXPORTS
By default, this module exports the C<validated_hash>,
=head1 IMPORTANT NOTE ON CACHING
-When C<validate> or C<validatep> are called the first time, the
-parameter spec is prepared and cached to avoid unnecessary
-regeneration. It uses the fully qualified name of the subroutine
-(package + subname) as the cache key. In 99.999% of the use cases for
-this module, that will be the right thing to do.
+When a validation subroutine is called the first time, the parameter spec is
+prepared and cached to avoid unnecessary regeneration. It uses the fully
+qualified name of the subroutine (package + subname) as the cache key. In
+99.999% of the use cases for this module, that will be the right thing to do.
However, I have (ab)used this module occasionally to handle dynamic
sets of parameters. In this special use case you can do a couple
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Fatal;
+
+use MooseX::Params::Validate qw( validated_hash );
+
+{
+ sub foo {
+ my %params = validated_hash(
+ \@_,
+ x => { isa => 'Int' },
+ y => { isa => 'Int' },
+ );
+ \%params;
+ }
+
+ sub bar {
+ my %params = validated_hash(
+ \@_,
+ x => { isa => 'Int' },
+ y => { isa => 'Int' },
+ MX_PARAMS_VALIDATE_ALLOW_EXTRA => 1,
+ );
+ \%params;
+ }
+}
+
+is_deeply(
+ bar( x => 42, y => 1 ),
+ { x => 42, y => 1 },
+ 'bar returns expected values with no extra params'
+);
+
+is_deeply(
+ bar( x => 42, y => 1, z => 'whatever' ),
+ { x => 42, y => 1, z => 'whatever' },
+ 'bar returns expected values with extra params'
+);
+
+like(
+ exception { foo( x => 42, y => 1, z => 'whatever' ) },
+ qr/The following parameter .+ listed in the validation options: z/,
+ 'foo rejects extra params'
+);
+
+done_testing();