属性为=>'Maybe[SomeSubtype]'returns属性()不传递类型约束
Attribute is => 'Maybe[SomeSubtype]' returns Attribute () does not pass type constraint
我已经创建了带有强制转换的子类型 Birth_d
,如下所示,我正在尝试将它与内置的 Maybe
类型结合使用,根据 Moose::Manual::Types。
我收到错误 You cannot coerce an attribute (birth_d) unless its type (Maybe[Birth_d]) has a coercion
。这是完整的测试代码:
package Student;
use Moose;
use Moose::Util::TypeConstraints;
use DateTime::Format::MySQL;
class_type 'Birth_d', { class => 'DateTime' };
coerce 'Birth_d',
from 'Str',
via { DateTime::Format::MySQL->parse_date( $_ ) };
has 'name' => (
isa => 'Str',
is => 'ro',
);
has 'birth_d' => (
isa => 'Maybe[Birth_d]', # This works: isa => 'Birth_d'
coerce => 1,
is => 'ro',
);
package main;
use Test::More;
my $student = Student->new(
name => 'Johnnie Appleseed',
birth_d => '2015-01-01'
);
is ( $student->birth_d->ymd(), '2015-01-01' );
my $student2 = Student->new(
name => 'Foo Bar',
birth_d => undef
);
is( $student2->birth_d, undef );
用 isa => 'Birth_d'
替换 isa => 'Maybe[Birth_d]'
可行,但不是所需要的。我需要使 birth_d 可选,如果未提供,则应为 undef。
我应该补充一下,我尝试使用 MooseX::Types 将这个 Birth_d 类型隐藏在一个单独的地方,但发现它对裸词的随意使用有点不正统,所以我慢慢退缩了。如果这样做有意义,我愿意重新考虑它。
我会发现没有 Maybe[Birth_d] 类型更有用,而只是用 Birth_d 类型声明属性,并且没有设置 "required"。
这样传入一个有效的String就会被接受,无效的String就会报错,什么都不用传进去
但是,您可以强制转换为 maybe 类型:
subtype 'MaybeBirth_d',
as maybe_type(class_type('DateTime'));
coerce 'MaybeBirth_d',
from 'Str',
via { DateTime::Format::MySQL->parse_date( $_ ) };
has 'birth_d' => (
isa => 'MaybeBirth_d',
coerce => 1,
is => 'ro',
);
我只是看不出能够为生日传递 undef 的价值 - 这比不设置它有什么好处?
我还想建议在包的末尾使用 no Moose::Util::TypeConstraints;
和 no Moose;
,或者在包的开头使用 namespace::autoclean;
,在包的末尾使用 __PACKAGE__->meta->make_immutable;
您的学生 class 结束。
Moose does not do any chaining of coercions,换句话说,你必须明确告诉它如何转换为 Maybe[Birth_d]
.
您可以通过重新使用现有的强制转换来做到这一点 Birth_d
:
package Student;
use Moose;
use Moose::Util::TypeConstraints;
use DateTime::Format::MySQL;
# save the Moose::Meta::TypeConstraint object
# you can also get it with find_type_constraint('Birth_d')
my $birth_d = class_type 'Birth_d', { class => 'DateTime' };
coerce 'Birth_d',
from 'Str',
via { DateTime::Format::MySQL->parse_date( $_ ) };
subtype 'MaybeBirth_d',
as 'Maybe[Birth_d]';
coerce 'Maybe[Birth_d]',
from 'Str|Undef',
via { $birth_d->coerce($_) };
has 'name' => (
isa => 'Str',
is => 'ro',
);
has 'birth_d' => (
isa => 'Maybe[Birth_d]',
coerce => 1,
is => 'ro',
predicate => 'has_birth_d', # as per your comment
);
package main;
use Test::More;
my $student = Student->new(
name => 'Johnnie Appleseed',
birth_d => '2015-01-01'
);
is ( $student->birth_d->ymd(), '2015-01-01' );
my $student2 = Student->new(
name => 'Foo Bar',
birth_d => undef
);
is( $student2->birth_d, undef );
ok( $student2->has_birth_d );
done_testing;
我已经创建了带有强制转换的子类型 Birth_d
,如下所示,我正在尝试将它与内置的 Maybe
类型结合使用,根据 Moose::Manual::Types。
我收到错误 You cannot coerce an attribute (birth_d) unless its type (Maybe[Birth_d]) has a coercion
。这是完整的测试代码:
package Student;
use Moose;
use Moose::Util::TypeConstraints;
use DateTime::Format::MySQL;
class_type 'Birth_d', { class => 'DateTime' };
coerce 'Birth_d',
from 'Str',
via { DateTime::Format::MySQL->parse_date( $_ ) };
has 'name' => (
isa => 'Str',
is => 'ro',
);
has 'birth_d' => (
isa => 'Maybe[Birth_d]', # This works: isa => 'Birth_d'
coerce => 1,
is => 'ro',
);
package main;
use Test::More;
my $student = Student->new(
name => 'Johnnie Appleseed',
birth_d => '2015-01-01'
);
is ( $student->birth_d->ymd(), '2015-01-01' );
my $student2 = Student->new(
name => 'Foo Bar',
birth_d => undef
);
is( $student2->birth_d, undef );
用 isa => 'Birth_d'
替换 isa => 'Maybe[Birth_d]'
可行,但不是所需要的。我需要使 birth_d 可选,如果未提供,则应为 undef。
我应该补充一下,我尝试使用 MooseX::Types 将这个 Birth_d 类型隐藏在一个单独的地方,但发现它对裸词的随意使用有点不正统,所以我慢慢退缩了。如果这样做有意义,我愿意重新考虑它。
我会发现没有 Maybe[Birth_d] 类型更有用,而只是用 Birth_d 类型声明属性,并且没有设置 "required"。
这样传入一个有效的String就会被接受,无效的String就会报错,什么都不用传进去
但是,您可以强制转换为 maybe 类型:
subtype 'MaybeBirth_d',
as maybe_type(class_type('DateTime'));
coerce 'MaybeBirth_d',
from 'Str',
via { DateTime::Format::MySQL->parse_date( $_ ) };
has 'birth_d' => (
isa => 'MaybeBirth_d',
coerce => 1,
is => 'ro',
);
我只是看不出能够为生日传递 undef 的价值 - 这比不设置它有什么好处?
我还想建议在包的末尾使用 no Moose::Util::TypeConstraints;
和 no Moose;
,或者在包的开头使用 namespace::autoclean;
,在包的末尾使用 __PACKAGE__->meta->make_immutable;
您的学生 class 结束。
Moose does not do any chaining of coercions,换句话说,你必须明确告诉它如何转换为 Maybe[Birth_d]
.
您可以通过重新使用现有的强制转换来做到这一点 Birth_d
:
package Student;
use Moose;
use Moose::Util::TypeConstraints;
use DateTime::Format::MySQL;
# save the Moose::Meta::TypeConstraint object
# you can also get it with find_type_constraint('Birth_d')
my $birth_d = class_type 'Birth_d', { class => 'DateTime' };
coerce 'Birth_d',
from 'Str',
via { DateTime::Format::MySQL->parse_date( $_ ) };
subtype 'MaybeBirth_d',
as 'Maybe[Birth_d]';
coerce 'Maybe[Birth_d]',
from 'Str|Undef',
via { $birth_d->coerce($_) };
has 'name' => (
isa => 'Str',
is => 'ro',
);
has 'birth_d' => (
isa => 'Maybe[Birth_d]',
coerce => 1,
is => 'ro',
predicate => 'has_birth_d', # as per your comment
);
package main;
use Test::More;
my $student = Student->new(
name => 'Johnnie Appleseed',
birth_d => '2015-01-01'
);
is ( $student->birth_d->ymd(), '2015-01-01' );
my $student2 = Student->new(
name => 'Foo Bar',
birth_d => undef
);
is( $student2->birth_d, undef );
ok( $student2->has_birth_d );
done_testing;