次のサブタイプと強制変換チェーンでは、何が欠けていますか?深い強制強制 - ユーザー定義型のArrayRef
- 強制可能文字列混合強制可能の
- 有効な文字列
- 配列リファレンスおよび有効な文字列
:私は検証型の配列リファレンスを強制するか、次の入力から死ぬできるようにしたいと思いますすべての型が完全に名前空間を持ち、宣言されていない関数validate
とcoerce_str
が(boolを返す)検証し、入力から有効な文字列をそれぞれ返すと仮定します。
subtype 'CustomType'
=> as 'Str'
=> where { validate($_) }
;
coerce 'CustomType'
=> from 'Str'
=> via { if (my $coerced = coerce_str($_)) {
return $coerced;
}
return $_;
}
;
subtype 'ArrayRefofCustomTypes'
=> as 'ArrayRef[CustomType]'
;
coerce 'ArrayRefofCustomTypes'
=> from 'CustomType'
=> via { [ $_ ] }
;
has 'values' => (is => 'ro', required => 1,
isa => 'ArrayRefofCustomTypes',
coerce => 1,
);
私はカスタムタイプの作品を知っています。私はそれを属性として定義し、強制的な文字列または既に有効な文字列を使用してオブジェクトを初期化することができます。どのようにすればよいかわからないのは、渡された配列リファレンスをコンストラクタから掘り下げて明示的に処理し、含まれているすべての文字列を個別に検証することです。私は深い強制(http://search.cpan.org/dist/Moose/lib/Moose/Manual/Types.pod#Deep_coercion)のドキュメントを数回読んできました。私はちょうどそれを得ておらず、誰かが私を正しい方向に向けることを望んでいます。ありがとう!
ここで、私はより簡潔に、それを概説するためにそれを切り詰め、しかしたい:
{
package My::Class;
use strict;
use warnings;
use Moose;
use Moose::Util::TypeConstraints;
subtype 'CustomType'
=> as 'Str'
=> where { validate($_) }
;
coerce 'CustomType'
=> from 'Str'
=> via { if (my $coerced = coerce_str($_)) {
return $coerced;
}
return $_;
}
;
subtype 'ArrayRefofCustomTypes'
=> as 'ArrayRef[CustomType]'
;
coerce 'ArrayRefofCustomTypes'
=> from 'CustomType'
=> via { [ $_ ] }
;
has 'values' => (is => 'ro', required => 1,
isa => 'ArrayRefofCustomTypes',
coerce => 1,
);
sub validate {
my $val = shift;
if ($val =~ /^\w+$/) {
return 1;
}
return();
}
sub coerce_str {
my $val = shift;
$val =~ s/\W/_/g;
return $val;
}
}
{
package main;
use strict;
use warnings;
use Test::More qw/no_plan/;
new_ok('My::Class' => [ values => [ 'valid' ] ]); #ok
new_ok('My::Class' => [ values => [ qw/valid valid still_valid/ ] ]); #ok
new_ok('My::Class' => [ values => 'valid' ]); # ok
new_ok('My::Class' => [ values => [ 'invalid; needs some coercion - ^&%&^' ] ]); #not ok
new_ok('My::Class' => [ values => 'invalid; needs some coercion - ^&%&^' ]); # not ok
cmp_ok(My::Class::coerce_str('invalid; needs some coercion - ^&%&^'), 'eq', 'invalid__needs_some_coercion________', 'properly coerces strings'); #ok
}
-であるとして、以下の私に与えることを実行しています。問題は、検証ではありませんが、私は明示的に自分の型変換を定義していないよということ、そして私が欠けているかわからないんだけど:あなたが使用
ok 1 - The object isa My::Class
ok 2 - The object isa My::Class
ok 3 - The object isa My::Class
not ok 4 - new() died
# Failed test 'new() died'
# at testcoercion.pl line 63.
# Error was: Attribute (values) does not pass the type constraint because: Validation failed for 'ArrayRefofCustomTypes' with value [ "invalid; needs some coercion - ^&%&^" ] at C:/strawberry/perl/site/lib/Moose/Meta/Attribute.pm line 1131
<<cut>>
not ok 5 - new() died
# Failed test 'new() died'
# at testcoercion.pl line 64.
# Error was: Attribute (values) does not pass the type constraint because: Validation failed for 'ArrayRefofCustomTypes' with value "invalid; needs some coercion - ^&%&^" at C:/strawberry/perl/site/lib/Moose/Meta/Attribute.pm line 1131
<<cut>>
ok 6 - properly coerces strings
1..6
# Looks like you failed 2 tests of 6.
つ注 - 私は=> {}介し「配列リファレンス[STR]」から '強制「ArrayRefofCustomTypes」=>を追加'と私の強制コードを複製し、それを処理container'll配列リファレンスにそれを貼り付ける疑いますそれは文字列 - >カスタム型変換コード全体を複製します。ドキュメンテーションを読み返すことから、これはすべての変換を明示的に定義する必要があることを意味するものですが、そのようなコードを複製することは嫌です。 – Oesor