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

Reply via email to