Hi All,
I've got a question that I didn't see addressed in any of the fine Moose
documentation... or maybe I just missed it. At any rate, it seems like a
common enough case that I thought others may benefit from my problem...
Say I have an attribute that represents a one-to-many relationship
implemented as a HashRef of ArrayRef of Str: that is, I have a list of keys,
each of which is associated with a corresponding list of tags.
I'd like to use the Moose::Meta::Attribute::Native::* trait-methods to
simplify these accesses if possible.
I understand from Moose::Manual::Attributes that I can assign multiple
Traits to an attribute (although this is mentioned in passing and not
illustrated well)... but I'm unclear about how this feature could be used in
this case (it seems like it should be useful here, and I have a creeping
suspicion that I've missed something totally obvious).
So anyway, given a key from this one-to-many mapping attribute I'd like to
be able to gracefully add (or delete, or verify, etc) an item to the
referenced ArrayRef. Using M::M::A::N::Trait::Hash by itself seems
straightforward, but I'm having trouble with implementing accesses to the
embedded ArrayRef as cleanly as I'd like...
The best solution I've come up with so far is to declare the required
array-handling convenience functions from M::M::A::N::Trait::Array in
'handles', and then use various 'around' method modifiers, to pick apart the
HashRef manually and delegate back to the handles-declared ...Trait::Array
functions, something like this:
has 'mapping' => (
traits => [ 'Hash', 'Array' ],
is => 'rw',
isa => 'HashRef[ ArrayRef[ Str ] ]',
default => sub { {} },
handles => {
add_tag => 'push',
# etc...
},
);
around add_tag ( $orig, $self, $key, $tag ){
# Pick apart the 'mapping' HashRef manually using $key
# Then...
$self->orig( $tag );
}
Although that's not totally horrible, it's easy to see how a lot of similar
boilerplate would build-up (and eventually need to be factored out of) the
'around' method modifiers which, although totally cool in-general, seem to
pollute the otherwise declarative and minimal beauty of Moose in this
particular case. :-(
Since it's possible to assign multiple Traits to an attribute it seems like
there'd be an easier way to simply declare such functionality in 'handles'
directly by chaining the ...Trait::Hash methods to the ...Trait::Array
methods. It's just not obvious to me what the syntax to implement such a
thing might be. Can anyone offer some insight into how something like this
might be implemented?
If chaining M::M::A::N handlers isn't natively possible, does anyone have a
suggestion for a better way to implement the functionality I'm describing?
Since a Trait is a Role under-the-covers (or so I've read) would I be able
to simply implement a new Role to handle a "compound-trait", then just
declare e.g. "traits => [ 'HashofArray' ]" and implement attribute-specific
aliases in this attribute to my new Role's methods?
Thanks in advance!
Montgomery