My Moose object has an attribute that is an arrayref of strings. I want to make it possible to set it to a single-element list by passing only a single string ('string'
), instead of an arrayref of a single string (['string']
).
has 'my_list' => (
is => 'rw',
isa => 'ArrayRef[Str]',
);
What is the proper way of solving this? Through a trigger
?
I'm not sure yet if I'll need this in both the object constructor and the attribute setter, or only in the constructor.
The best way to approach this is by using type coercion (creating one type from another).
Note, that it's a bad idea to coerce into standard Moose types, so we also create a subtype.
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
package MyClass;
use Moose;
use Moose::Util::TypeConstraints; # defines 'subtype' and 'coerce'
# Our new subtype
subtype 'ArrayRefofStr',
as 'ArrayRef[Str]';
# Define the coercion from a string to
# and array of strings
coerce 'ArrayRefofStr',
from 'Str',
via { [ $_ ] };
has 'my_list' => (
is => 'rw',
isa => 'ArrayRefofStr', # Change to subtype
coerce => 1, # Turn on type coercion
);
package main;
my $obj1 = MyClass->new(my_list => ['foo']);
my $obj2 = MyClass->new(my_list => 'bar' );
say $obj1->my_list->[0];
say $obj2->my_list->[0];