Excerpts from Emmanuel Quevillon's message of Tue Sep 01 08:29:06 -0400 2009:
> I am quite new to Moose, at least I don't use all the power of it.
> Anyway, I tried to create a subtype called 'ArrayRefOrHashRef' to be
> able to have an attribute that could accept and array ref or a hash
> ref. My idea is to :
> 
> 1) If the parameter passed to my attribute is an array ref, work
> with it and then create a hash ref at the end
> 2) It the parameter passed to my attribute is a hash ref, check some
> stuff then return it modified or not.

You don't want an attribute that accepts an arrayref or hashref.  You want an
attribute that accepts a hashref with very specific keys.

Type constraints should specify the value you want to end up with, not the
values you could start with.  (That's what coercions are for.)

> However,if I passed an array ref to 'cut_types'
> it does not get transform to a hash ref.

That's because all you said in your constraint was that it needed to be an
arrayref, so as far as Moose knows, there's no reason to run the coercion.

You probably want something like this (using MooseX::Types::Structured):

  subtype ValidCutTypes,
    as Dict[
      cohesive => ArrayRef[Str],
      blunt    => ArrayRef[Str],
    ];

  coerce ValidCutTypes,
    from ArrayRef,
    via { 
      my %defaults = (cohesive => [qw/5' 3'/], blunt => ['blunt']);
      [ map { $_ => $defaults{$_} } @$_ ];
    },
    from HashRef,
    via { ... whatever you need to do to a hashref ... };

  # later on
  
  has cut_types => (
    is => 'ro',
    isa => ValidCutTypes,
    coerce => 1,
    default => sub { ... },
  );

Some notes:

* ArrayRef[Str] for the values in ValidCutTypes is just a guess based on your
  existing defaults -- I don't know anything about your real problem domain.
* You don't need to check the keys returned from the ArrayRef coercion, because
  the Dict[] type constraint will already do that.
* required => 1 is pretty much meaningless when you provide a default.


hdp.

Reply via email to