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.
CodePudding user response:
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];