Home > Software design >  How to process the argument in a Moose attribute setter before setting?
How to process the argument in a Moose attribute setter before setting?

Time:04-11

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];
  • Related