2
votes

I am trying to figure out the proper way to incorporate Moose in my project. Here I found an article suggesting that Moose types should be organized in type libraries, which seems like a good idea. So I wrote the following code basing on the provided example:

file 1: MyTypeLib.pm

package MyTypeLib;
use MooseX::Types -declare => [ qw( MyStatus ) ];
use MooseX::Types::Moose qw/Int/;

subtype MyStatus,
      as Int,
      where { $_ >= 0 && $_ < 10 },
      message { "Wrong status: $_" };

1;

file 2: MyTest.pm

package MyTest;
use MyTypeLib qw( MyStatus );
use Moose;

has status => ( is => 'rw', isa => 'MyStatus' );

no Moose; 1;

file 3: MyMain.pl

use strict;
use warnings;
use MyTest;

my $t1 = MyTest->new('status' => 5);

When I run it I get this message:

Attribute (status) does not pass the type constraint because: Validation failed for 'MyStatus' with value 5 (not isa MyStatus) at C:\Strawberry\perl\vendor\lib\Moose\Object.pm line 24

When I keep subtype definition in MyTest.pm and don't use MooseX::Types, everything works as expected. But the point is to move subtypes to a separate package and use them in other packages. Could someone please advise how to make it work, or point to (or post) some working example, or suggest the alternative way of achieving the goal.

Thank you!

2

2 Answers

2
votes

Remove the quotes: isa => MyStatus, not isa => 'MyStatus'. MyStatus is a constant-like function exported from your type library. Providing a string rather than a proper type constraint for isa ("stringy types") causes it to be looked up in Moose's type registry, or, if it's not found there, it's interpreted as the name of a class, and the type is inferred to be "any object of that class or its subclasses". Stringy types are less explicit and less flexible than using actual types, and more prone to conflicts since they all share a global namespace. It's best not to use them and type lbraries at the same time.

0
votes

This seems to work

MyTypeLib.pm

package MyTypeLib;
use Moose::Util::TypeConstraints;

subtype MyStatus =>
      as 'Num' =>
      where { $_ >= 0 && $_ < 10 },
      message { "Wrong status: $_" };

#coerce MyStatus => from Int => via { $_ };
1;

MyTest.pm

package MyTest;
use MyTypeLib;
use Moose;

has status => ( is  => 'rw', 
                isa => 'MyStatus', 
                #coerce => 1 i
);

no Moose; 1;

MyMain.pl

use strict;
use warnings;
use MyTest;
use Data::Dumper;

my $t1 = MyTest->new( status => 5);
print Dumper $t1;
my $t2 = MyTest->new( status => 10);

Which gives

$ perl MyMain.pl
$VAR1 = bless( {
                 'status' => 5
               }, 'MyTest' );
Attribute (status) does not pass the type constraint because: Wrong
status: 10 at /System/Library/Perl/Extras/5.18/darwin-thread-multi-
2level/Moose/Exception.pm line 37

There isn't much information on this aspect of Moose but it looks like Moose::Util::TypeConstraints is the MooseX module folded into Moose.


EDIT Removed coerce!

You also need an explicit coercion.-