'How to process the argument in a Moose attribute setter before setting?
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.
Solution 1:[1]
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];
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Dave Cross |
