Hey, based on your dumps, I'm not sure you are on the latest MX:Types and all.  
Could you check that so that I can start to look through this and see if there 
are any bugs I can create a test case out of?  Thanks!

john



----- Original Message ----
From: Stevan Little <stevan.lit...@iinteractive.com>
To: i...@sillit.com
Cc: moose@perl.org
Sent: Thursday, January 29, 2009 1:13:03 PM
Subject: Re: MooseX::Types : subtype/coerce not found in Roles  
(hand_optimized_type_constraint?)

I tend to do the following:

- make a MyApp::Types package that handles *all* custom type  
definitions and type coercions
- make all other packages load MyApp::Types (even if they dont need  
it, because their deps might need it)

Then as far as circular refs are concerned, they are tricky and each  
case is a little different. The key is to map out what you need and  
the force things to load in that order (this is where the global  
MyApp::Types can be really handy).

Also, find_type_constraint is your friend, it is exported from  
Moose::Util::TypeConstraints and can basically be used to detect if  
the type already exists or not. Something like:

if (find_type_constraint('Foo')) {
     # do something wiht the Foo type here, like add a coercion
}

Of course the ideal situation is that you break your circular refs  
instead, but sometimes that is just not possible.

- Stevan

On Jan 29, 2009, at 11:59 AM, i...@sillit.com wrote:

> Stevan,
>
> Many thanks for getting back so quickly - that sounds exactly the sort
> of thing that must be happening.
>
> Before I dive in - could I ask what the recommended best practice for
> avoiding circular "use" cases is (if any)? I've generally tried to
> "use" all the modules required by the package to keep each package as
> independent as possible without loading everything unneccessarily. Or
> am I missing something?
>
> Cheers
>
> Ian
>
> On 29/01/2009, Stevan Little <stevan.lit...@iinteractive.com> wrote:
>> Ian,
>>
>> Types can sometimes be very sensitive to load order since they are
>> really done at runtime (it is the runtime immediately following
>> compile time, but still runtime). Based on your description I think
>> you are getting bitten by the auto-creation of types (if Moose  
>> doesn't
>> know the type it makes it into a Object subtype that isa(<name of
>> type>)).
>>
>> I would check to make sure that you do not have any circular
>> dependencies in how you load your modules, Perl will handle these
>> fine, but Moose types will be sensitive to the order in which the
>> circle is traversed.
>>
>> - Stevan
>>
>> On Jan 29, 2009, at 6:54 AM, Ian Sillitoe wrote:
>>
>>> Hello,
>>>
>>> I have a problem with subtype/coercions (MooseX::Types library) that
>>> I've
>>> spent ages trying to understand, then ages trying abstract into a
>>> simple
>>> test case but all simple cases seem to work as expected but just not
>>> in my
>>> larger code base. I was hoping that if I put the symptoms up someone
>>> may
>>> spot what is going on and put me out of my misery (or at least point
>>> me to
>>> where I should continue my digging).
>>>
>>> Please excuse any typos in the (incomplete) example code below. I
>>> have coded
>>> up a full version of this simple scenario and I can't replicate the
>>> error
>>> I'm getting in my real code base anyway - so this is meant purely  
>>> for
>>> illustration.
>>>
>>> # Types library
>>> package My::Types;
>>> use Moose;
>>> use MooseX::Types -declare [qw( Version DomainID )];
>>> use My::Version;
>>>
>>> subtype 'Version',
>>>   as 'Object',
>>>   where { $_->isa( 'My::Version' ) };
>>>
>>> coerce 'Version',
>>>   from 'Str',
>>>   via { My::Version::init_from_string( $_ ) };
>>>
>>> subtype 'ObjectID',
>>>   as 'Str';
>>>
>>> # Role to associate versions with objects
>>> package My::Role::Verisoned;
>>> use Moose::Role;
>>> use My::Types qw(Version);
>>> has 'version' => (is => 'rw', isa => 'Version', coerce => 1);
>>>
>>> # Versioned Object1
>>> package My::Object1;
>>> use Moose;
>>> with 'My::Role::Versioned';
>>>
>>> # Versioned Object2
>>> package My::Object2;
>>> use Moose;
>>> use My::Types qw( DomainID );
>>> use My::Object1;
>>> with 'My::Role::Versioned';
>>>
>>> has 'domain_id' => ( is => 'rw', isa => 'DomainID' );
>>>
>>> sub get_object1 {
>>>   my $self = shift;
>>>   return My::Object1->new( version => $self->version );
>>> }
>>>
>>> In this simple case, the subtype/coerce works as expected in both
>>> objects
>>> (the type constaint of the 'version' attribute is the identical)
>>>
>>> $o2 = My::Object2->new( version => '3.2' );
>>> $o1 = $o2->get_object1;
>>>
>>> warn "Object1: " .
>>> My::Object1->meta->get_attribute_map->{version}->{type_constraint}-
>>>> dump;
>>> warn "Object2: " .
>>> My::Object2->meta->get_attribute_map->{version}->{type_constraint}-
>>>> dump;
>>>
>>> Object1: $VAR1 = bless( {
>>>                   'compiled_type_constraint' => 'CODE(0xa41e310)',
>>>                   'parent' => 'My::Version',
>>>                   'coercion' =>
>>> 'Moose::Meta::TypeCoercion=HASH(0xa991c70)',
>>>                   'name' => 'Version',
>>>                   'constraint' => 'CODE(0x9eb4600)',
>>>                   'package_defined_in' => 'My::Types'
>>>               }, 'Moose::Meta::TypeConstraint' );
>>>
>>> Object2: $VAR1 = bless( {
>>>                   'compiled_type_constraint' => 'CODE(0xa41e310)',
>>>                   'parent' => 'My::Version',
>>>                   'coercion' =>
>>> 'Moose::Meta::TypeCoercion=HASH(0xa991c70)',
>>>                   'name' => 'Version',
>>>                   'constraint' => 'CODE(0x9eb4600)',
>>>                   'package_defined_in' => 'My::Types'
>>>               }, 'Moose::Meta::TypeConstraint' );
>>>
>>> However, in what seems to be a similar scenario in my live code, I
>>> get the
>>> error that the 'version' attribute doesn't pass the type constraint
>>> when
>>> creating an instance of Object1 inside Object2::get_object1 (it no
>>> longer
>>> seems to be aware of the subtype/coercion in My::Types):
>>>
>>> Attribute (version) does not pass the type constraint because:
>>> Validation
>>> failed for 'Version' failed with value
>>> My::Version::V3_2_0=HASH(0x1aea0930)
>>> at .../Moose/Meta/Attribute.pm line 415
>>>
>>> When I look at the type constraint of the 'version' attribute in
>>> these two
>>> classes they now appear different:
>>>
>>> warn "Object1: " .
>>> My::Object1->meta->get_attribute_map->{version}->{type_constraint}-
>>>> dump;
>>> warn "Object2: " .
>>> My::Object2->meta->get_attribute_map->{version}->{type_constraint}-
>>>> dump;
>>>
>>> Object1: $VAR1 = bless( {
>>>                'compiled_type_constraint' => 'CODE(0x1ae87c00)',
>>>                'parent' => 'Object',
>>>                'hand_optimized_type_constraint' =>
>>> $VAR1->{'compiled_type_constraint'},
>>>                'name' => 'Version',
>>>                'constraint' => 'CODE(0x1a3c4b80)',
>>>                'class' => 'Version'
>>>              }, 'Moose::Meta::TypeConstraint::Class' );
>>>
>>> Object2: $VAR1 = bless( {
>>>                'compiled_type_constraint' => 'CODE(0x1a929c10)',
>>>                'parent' => 'My::Version',
>>>                'coercion' =>
>>> 'Moose::Meta::TypeCoercion=HASH(0x1ae9da00)',
>>>                'name' => 'Version',
>>>                'constraint' => 'CODE(0x1a3c4b80)',
>>>                'package_defined_in' => 'My::Types'
>>>              }, 'Moose::Meta::TypeConstraint' );
>>>
>>>
>>> I hope that difference shows what I might be doing wrong or where to
>>> start
>>> looking (parent => 'Object'? hand_optimized_type_constraint?). This
>>> change
>>> appears to be related to which modules have been "use"d -- in my
>>> live code I
>>> can remove this error by *taking out* the equivalent of "use
>>> My::Types" on
>>> Object2.
>>>
>>> Very much appreciate any help/pointers.
>>>
>>> Cheers,
>>>
>>> Ian
>>>
>>>
>>> --
>>> Ian Sillitoe
>>> CATH Team -- http://cathdb.info
>>
>>
>
>
> -- 
> Ian Sillitoe
> CATH Team -- http://cathdb.info


      

Reply via email to