Using BUILDARGS to avoid effects at a distance:
{
package Page;
use strict;
use warnings;
use Moose;
has 'url' => (
is => 'ro',
isa => 'Str',
required => 1,
);
no Moose;
__PACKAGE__->meta->make_immutable();
}
{
package Container;
use strict;
use warnings;
use Moose;
my $pages_constraint = Moose::Util::TypeConstraints::create_paramet
+erized_type_constraint('ArrayRef[Page]');
my $aoh_constraint = Moose::Util::TypeConstraints::create_paramet
+erized_type_constraint('ArrayRef[HashRef]');
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
my %args = ( @_ == 1 ? %{ $_[0] } : @_ );
if (exists($args{pages})) {
my $pages = $args{pages};
if (!$pages_constraint->check($pages)) { # Need to coerce?
if ($aoh_constraint->check($pages)) { # Can we coerce?
$args{pages} = [ map Page->new($_), @$pages ];
}
}
}
return $class->$orig(%args);
};
has 'pages' => (
is => 'rw',
isa => 'ArrayRef[Page]',
default => sub { [ ] },
);
no Moose;
__PACKAGE__->meta->make_immutable();
}
Container->new( pages => [ { url => "a" }, { url => "b" } ] );
This is basically the same approach you tried, but correctly uses the more appropriate BUILDARGS instead of BUILD.
Coded so it can take both ArrayRef[HashRef] and ArrayRef[Page].
|