tj_thompson has asked for the wisdom of the Perl Monks concerning the following question:
Hello Monks!
I'm back with another Moose question. Fortunately, this one's easy to lay out.
I have the following code:
package Point; use Moose; use namespace::autoclean; has 'x' => ( isa => 'Int', is => 'rw', required => 1 ); has 'y' => ( isa => 'Int', is => 'rw', required => 1 ); package Named; use Moose::Role; use namespace::autoclean; has 'name' => ( isa => 'Str', is => 'rw', required => 1 ); package main; use Moose::Util; my $p = Point->new( x => 1, y => 1 ); my $role = 'Named'; $role->meta->apply( $p ); # <-- line 41 print $p->dump;
This code fails with the following:
Attribute (name) is required at /nfs/pdx/disks/nehalem.pde.077/perl/5. +12.2/lib64/site_perl/x86_64-linux/Moose/Meta/Attribute.pm line 514 ...<snipping unnecessary trace info>.. Moose::Meta::Role::apply('Moose::Meta::Role=HASH(0x114b110)', 'Moose:: +Meta::Class::__ANON__::SERIAL::1=HASH(0xfc2748)') called at /nfs/pdx/ +disks/nehalem.pde.077/scripts/test3.pl line 41
The problem is that the 'name' attribute in the Named role is required. However, I've already created my Point instance before I compose the Named role into this. This problem goes away if you remove the required parameter from the 'name' attribute in the Named role.
Obviously, there are many workarounds to this issue. Disabling the required parameter and initializing the attribute after role application is one. Ensuring the attribute is already defined by the instance is another. Composing the role into the class prior to instantiation is a third.
I believe having to remove the required parameter from the attribute and relying on the programmer to remember to properly initialize the attribute is the wrong way to do this. Moose provides the required parameter explicitly to ensure that a given attribute is properly initialized. Ensuring the instance already has an attribute that satisfies the requirement seems to be a convoluted way to solve the issue, definitely worse than the first workaround. Composing the role into the class prior to instantiation limits flexibility as I am trying to apply differing roles to differing instances.
So, the summary: Is there a good way to compose a role with a required attribute into an instance other than what I've outlined above?
Thanks in advance for taking the time to read my question, it is always appreciated!
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Moose composing role with required attribute into existing instance
by jandrew (Chaplain) on Aug 03, 2012 at 18:48 UTC | |
by tj_thompson (Monk) on Aug 03, 2012 at 20:02 UTC | |
by jandrew (Chaplain) on Aug 03, 2012 at 20:33 UTC | |
by tj_thompson (Monk) on Aug 03, 2012 at 19:55 UTC |