需要制作一个接受一个或多个paths
的模块,并将它们强制转换为Class::Path
数组。在CPAN中存在一个模块MooseX::Types::Path::Class。从它的来源我发现,模块定义了子类型Dir
和File
。
我的示例模块:
package Web::Finder;
use namespace::sweep;
use Modern::Perl;
use Moose;
use MooseX::Types::Path::Class qw(Dir); #??? - is this correct?
use Method::Signatures::Simple;
use Path::Class;
#should accept one or more directories as Str or as Path::Class::Dir
has 'volumes' => (
is => 'ro',
isa => 'ArrayRef[Path::Class::Dir]', #Can I use here a simple 'ArrayRef[Dir]' ?
required => 1,
coerce => 1,
);
has 'fs' => (
is => 'ro',
isa => 'ArrayRef[File::System]',
lazy => 1,
builder => '_create_volumes',
);
#is the next correct?
method _create_volumes {
push $self->fs, File::System->new('Real', root => $_->stringify) for ($self->volumes);
}
和我的剧本
#!/usr/bin/env perl
use Modern::Perl;
use Web::Finder;
my $f = Web::Finder->new(volumes => .... ???
我应该在上面的模块中更改以接受下一次初始化?
my $f = My::Module->new(volumes => "/some/path");
和
my $f = My::Module->new(volumes => [qw(/some/path1 /another/path2)] );
或类似的东西 - 所以:一条或多条路径......
从我理解的错误信息中,我做错了...;)
You cannot coerce an attribute (volumes) unless its type (ArrayRef[Path::Class::Dir]) has a coercion at Web/Finder.pm line 14.
require Web/Finder.pm called at x line 2
main::BEGIN() called at Web/Finder.pm line 0
eval {...} called at Web/Finder.pm line 0
Attribute (volumes) does not pass the type constraint because: Validation failed for 'ArrayRef[Path::Class::Dir]' with value ARRAY(0x7f812b0040b8) at constructor Web::Finder::new (defined at Web/Finder.pm line 33) line 42.
Web::Finder::new("Web::Finder", "volumes", ARRAY(0x7f812b0040b8)) called at x line 6
问题的下一部分是如何为每个volume
一个File::System实例创建。 builder
方法是否正确?
对任何帮助和/或评论都很满意。
答案 0 :(得分:2)
要从一个或多个路径强制,您需要声明这些类型的强制。 MooseX :: Types :: Path :: Class确实定义了强制而不是你需要的强制(它们只会强制转换为单个的Path :: Class对象,而不是它们的数组)。
subtype 'ArrayOfDirs', as 'ArrayRef[Path::Class::Dir]';
coerce 'ArrayOfDirs',
# for one path
from 'Str', via { [ Path::Class::Dir->new($_) ] },
# for multiple paths
from 'ArrayRef[Str]', via { [ map { Path::Class::Dir->new($_) } @$_ ] };
has 'volumes' => (
is => 'ro',
isa => 'ArrayOfDirs',
required => 1,
coerce => 1,
);
builder
方法应返回 FileRef的FileRef对象。
sub _create_volumes {
my ($self) = @_;
return [
map { File::System->new('Real', root => $_->stringify) }
$self->volumes
];
}
您可以将卷声明为'ArrayRef[Dir]'
吗?不,不是那种形式。 MooseX中的Dir
:: Types :: Path :: Class被定义为MooseX::Types类型,这意味着它需要用作一个单词而不是一个字符串。
use MooseX::Types::Moose qw( ArrayRef );
use MooseX::Types::Path::Class qw( Dir );
has 'volumes' => (
is => 'ro',
isa => ArrayRef[Dir],
required => 1,
coerce => 1,
);