Hi list
I've stumbled upon (what I think is) a misleading error message from
from_object(). Basically, the following code
my $now = DateTime->now;
my $copy = DateTime->from_object( $now );
should tell me I've omitted the mandatory 'object =>' key (as the docs state,
so definitely my bad). However, the error message was confusing:
The following parameter was passed in the call to DateTime::from_object but
was not listed in the validation options: local_rd_secs
It seems I'm not the only person who's confused (e.g.,
http://code.google.com/p/panchanga/issues/detail?id=1 and a few more).
I've tried tracing the problem, but I admit it's beyond my comprehension. I
vaguely suspect the overloading, because DateTime->from_object( $whatever )
--with $whatever being anything else than a DateTime object-- fails as it
should, but I have no proof whatsoever.
I'm attaching a test script that exposes the behaviour, and an (ugly?)
workaround. Useful?
Best regards
Edward Baudrez
--
Royal Meteorological Institute of Belgium
Remote Sensing from Space
Ringlaan 3, 1180 Ukkel, Belgium
+32 2 373 0623
[email protected]
use strict;
use warnings;
use Test::More;
use Test::Exception;
use DateTime;
use Carp qw( longmess confess );
# BACKGROUND
# this is the right way to call DateTime->from_object() (from the docs): the 'object' key is mandatory
my $now = DateTime->now;
ok $now;
my $copy = DateTime->from_object( object => $now );
ok $copy;
# calling DateTime->from_object() without 'object' dies:
throws_ok { DateTime->from_object( {} ) } qr/^Mandatory parameter 'object' missing in call to DateTime::from_object$/m;
# however, the following two die with an error message that is less explicit:
throws_ok { DateTime->from_object( 1 ) } qr/^Odd number of parameters in call to DateTime::from_object when named parameters were expected$/m;
throws_ok { DateTime->from_object( [] ) } qr/^Odd number of parameters in call to DateTime::from_object when named parameters were expected$/m;
# and this gives a misleading error message:
throws_ok { DateTime->from_object( $now ) }
qr/^(Mandatory parameter 'object' missing in call to DateTime::from_object|Odd number of parameters in call to DateTime::from_object when named parameters were expected)$/m;
# fails instead with
# 'The following parameter was passed in the call to DateTime::from_object but was not listed in the validation options: local_rd_secs'
# INVESTIGATION
# inspecting the arguments that validate() receives (set $show_args = 1 below)
# shows that validate() receives the object as the only argument, but somehow
# fails to notice the absence of the 'object' key
*real_validate = \&DateTime::validate;
my $show_args = 0;
if( $show_args ) {
no warnings 'redefine';
local *DateTime::validate = sub (\@$) {
note longmess '- CALLING validate()';
note "\$_[$_] = ", explain $_[ $_ ] for 0 .. $#_;
&real_validate
};
eval { DateTime->from_object( $now ) };
}
# POSSIBLE WORKAROUND
*real_from_object = \&DateTime::from_object;
{
no warnings 'redefine';
local *DateTime::from_object = sub {
my $class = shift;
confess( "Mandatory parameter 'object' missing in call to " . (caller 0)[3] . "\n" ) unless grep /^object$/, @_;
real_from_object( $class, @_ );
};
throws_ok { DateTime->from_object( $now ) } qr/^Mandatory parameter 'object' missing in call to /;
}
done_testing;