【问题标题】:Path::Class::File or ::Dir & Moose initialiazation and coercionPath::Class::File 或 ::Dir & Moose 初始化和强制
【发布时间】:2014-05-01 03:44:56
【问题描述】:

目前有:

package Local;
use warnings;
use Moose;
use Method::Signatures::Simple;
use Path::Class::File;
use Path::Class::Dir;

method _build_path_class {
    my $str = $self->pathstr;
    return Path::Class::Dir->new($str) if (-d $str);
    return Path::Class::File->new($str);
}

has 'pathstr' => (is => 'rw', isa => 'Str', required => 1);
has 'path'    => (
    is => 'rw',
    lazy => 1,
    #isa => 'Path::Class::File|Path::Class::Dir', #this didn't work
    isa => 'Object',
    builder => '_build_path_class',
);

no Moose;
__PACKAGE__->meta->make_immutable();
1;

它正在工作,所以

my $d = Local->new(pathstr => '/tmp')->path;        #is isa Path::Class::Dir
my $f = Local->new(pathstr => "/etc/passwd)->path;  #is isa Path::Class::File 

寻找一个解决方案,而不是两个属性 pathstrpath 将只有一个 path 一个它应该强制Str 到:

  • Path::Class::Dir(如果Str 是目录)
  • Path::Class::File(在任何其他情况下)

类似:

package Local;
use warnings;
use Moose;
use Method::Signatures::Simple;
use Path::Class::File;
use Path::Class::Dir;

#how to coerce conditionally from Str to
coerce 'Path::Class::Dir',
    from Str, via { Path::Class::Dir->new($_) }; #but only if the Str is pointing to directory

#or to
coerce 'Path::Class::Dir',
    from Str, via { Path::Class::Fiel->new($_) }; #in all other cases

has 'path' => (
    is => 'rw',
    lazy => 1,
    isa => 'Path::Class::File|Path::Class::Dir', #<--How to write this corectly
    required => 1,
    coerce => 1,
);

no Moose;
__PACKAGE__->meta->make_immutable();
1;

已编辑,扩展了问题 - 因为获得了“不清楚在问什么”的密切投票。希望现在更清楚了。

作为记录,池上的工作版本:

package Ike;
use warnings;
use namespace::sweep;
use Moose;
use Moose::Util::TypeConstraints;

class_type('Path::Class::Entity');

coerce 'Path::Class::Entity',
   from 'Str',
      via {
         if (-d $_) {
            Path::Class::Dir->new($_)
         } else {
            Path::Class::File->new($_)
         }
      };

has 'path' => (
    is       => 'rw',
    isa      => 'Path::Class::Entity',
    required => 1,
    coerce   => 1,
);

__PACKAGE__->meta->make_immutable;
1;

我的测试程序

#!/usr/bin/env perl
use strict;
use warnings;
use Path::Class;
use Test::More tests => 8;
use Ike;

my $temp = Path::Class::tempdir(CLEANUP => 1);  #create tempdir for testing

my $d1 = dir($temp, "d1");
my $d2 = dir($temp, "d2");
$d1->mkpath;                #create a directory d1
symlink("$d1", "$d2");      #symlink d2 -> d1

my $f1 = file($temp,'f1');
my $f2 = file($temp,'f2');
$f1->touch;                 #create a file f1
symlink("$f1", "$f2");      #symlink f2 -> f1

sub getpath { return Ike->new( path => shift )->path; }

isa_ok( getpath( $d1 ), 'Path::Class::Dir' );
isa_ok( getpath( $d2 ), 'Path::Class::Dir' );
isa_ok( getpath( $f1 ), 'Path::Class::File' );
isa_ok( getpath( $f2 ), 'Path::Class::File' );

isa_ok( getpath("$d1"), 'Path::Class::Dir' );
isa_ok( getpath("$d2"), 'Path::Class::Dir' );
isa_ok( getpath("$f1"), 'Path::Class::File' );
isa_ok( getpath("$f2"), 'Path::Class::File' );

结果:

1..8
ok 1 - An object of class 'Path::Class::Dir' isa 'Path::Class::Dir'
ok 2 - An object of class 'Path::Class::Dir' isa 'Path::Class::Dir'
ok 3 - An object of class 'Path::Class::File' isa 'Path::Class::File'
ok 4 - An object of class 'Path::Class::File' isa 'Path::Class::File'
ok 5 - An object of class 'Path::Class::Dir' isa 'Path::Class::Dir'
ok 6 - An object of class 'Path::Class::Dir' isa 'Path::Class::Dir'
ok 7 - An object of class 'Path::Class::File' isa 'Path::Class::File'
ok 8 - An object of class 'Path::Class::File' isa 'Path::Class::File'

:)

【问题讨论】:

  • 您应该首先删除Modern::Perlnamespace::sweep。应避免使用表现为 pragma 的模块
  • Modern::Perl 的问题在于,很少有人(甚至你也不知道)确切地知道它的作用。如果你想要use strictuse warnings,那么你应该这样写

标签: perl moose coercion


【解决方案1】:
coerce 'Path::Class::Entity',  # Base class of ::Dir and ::File
   from Str,
      via {
         if (-d $_) {
            Path::Class::Dir->new($_)
         } else {
            Path::Class::File->new($_)
         }
      };

has 'path' => (
    is       => 'rw',
    lazy     => 1,
    isa      => 'Path::Class::Entity',
    required => 1,
    coerce   => 1,
);

如果路径不存在或发生其他错误,上述假设路径是文件的路径。

【讨论】:

  • 非常感谢! 与往常一样,您的答案准确、优美且正确。你是唯一一个通过我糟糕的英语阅读并真正理解我需要什么的人。 :) 再次感谢你,你的摇滚!
【解决方案2】:

在联合中使用它之前,您需要声明 Path::Class::File 和 PCD 类型(我认为)。尝试在此之前添加class_type('Path::Class::File')

或者更好的是,使用MooseX::Types::Path::Class

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多