通过胁迫

时间:2017-02-24 16:43:12

标签: perl oop moose coercion moosex-types

我尝试创建类型_Varchar但未成功使用其他类型_VarcharRange作为参数。反过来,_VarcharRange可以从其中一种Moose基类型中强制执行。

让我以_Varchar_Range为例开始

package MyTypes;

use strict;
use warnings;

use Moose;
use MooseX::Types::Moose qw(Str Int ArrayRef HashRef);
use MooseX::Types::Common::Numeric qw( PositiveOrZeroInt );
use MooseX::Types::Parameterizable qw(Parameterizable);
use MooseX::Types -declare=>[qw(_VarcharRange)];

subtype _VarcharRange,

    as HashRef[PositiveOrZeroInt], # Must ask for it from MooseX

    where {
        return 0 if ( grep {$_ ne 'min' && $_ ne 'max' } keys %{$_});
        return ( $_->{min} <= $_->{max} ) if ( defined $_->{max} && defined $_->{min} );
        return 1;
    },

    message {"Trololo"};

coerce _VarcharRange,

  from ArrayRef[PositiveOrZeroInt],

  via {
    my $result;
    my @keys = qw(min max);

    foreach my $val (reverse @$_) {
        my $key = pop @keys // 'bad_range';
        $result->{$key} = $val;
    }

    return $result;
  };

has 'my_range' => ( isa => _VarcharRange, is => 'ro', coerce => 1 );

1;

以及相应的测试文件:

!/usr/bin/env perl

use MyTypes qw(_VarcharRange);

my $check = MyTypes->new(
    #my_range => [5, 10],   # works fine
    #my_range => [1, 0],    # fails, as expected
    #my_range => [0, 1, 2], # fails, as expected
    #my_range => [10],      # works fine
);

到目前为止一切顺利,但现在我尝试添加_Varchar类型_VarcharRange。将其添加到MyTypes.pm

subtype _Varchar,

    as Parameterizable[Str, _VarcharRange],

    where {
        my ( $string, $range ) = @_;
        my $len = length($string);
        return 0 if ($range->{min} && $len < $range->{min});
        return 0 if ($range->{max} && $len > $range->{max});
        return 1;
    },

    message { "'$_[0]' length is not within range $_[1]->{min} - $_[1]->{max}" };

    has 'my_string' => ( isa => _Varchar[ [1, 10] ], is => 'ro' );

这不起作用。

我所期望的是_VarcharRange将通过来自[1, 10]数组引用的强制隐式创建。但看起来我的代码甚至没有继续创建_VarcharRange,因为我试图直接用_Varchar参数化我的ArrayRef

有没有办法实现我想要的?将数组引用作为参数传递,但具有强制中间类型_VarcharRange并实际用于参数化。

我不想直接从_Varchar参数化ArrayRef,因为它不是非常面向对象的。感觉就像一个范围的独立类型是正确的方式。

0 个答案:

没有答案