Moose attribute initialization
Asked Answered
B

1

6

What is the typical approach for custom initialization of certain attributes when using Moose?

For instance, suppose I take two dates in string format as input to my class:

has startdate  => (is => 'ro', isa => 'Str', required => 1);
has enddate    => (is => 'ro', isa => 'Str');

These dates come in as strings, but I need them formatted in a specific date format (ISO8601), without Moose I would just initialize them in new() but I am unsure about with Moose.

It seems that the viable options from reading the docs are in BUILDARGS, BUILD, or using coercion. Which of these would be most appropriate given that I have a function _format_as_iso8601() that can take a date and return it formatted correctly?

Bromley answered 28/2, 2014 at 19:40 Comment(0)
F
6

BUILD is called after the constructor, which makes it handy to verify state but not necessarily useful to format incoming arguments.

BUILDARGS would let you modify incoming arguments before the constructor is called, which makes it a better fit for this case. Your attribute is read-only, so this could work.

But... if you're hungry for static typing, why would you stop after promising "this is a string"? If you create a subtype for ISO8601 strings, you can promise "this is a string and it has X format". Even better, you're doing that in a way that's immediately and trivially portable to other attributes.

I rather doubt the regex below will work for you, but I hope it will get the point across:

#define the type
subtype 'iso8601',
    as 'Str',
    where { /\d{4}-\d{2}-\d{2}/ },
    message { "Not a valid ISO8601 string ($_)" };

#provide a coercion
coerce 'iso8601',
    from 'Str',
    via { _format_as_iso8601 $_ };

#tell moose to coerce the value
has startdate  => (is => 'ro', isa => 'iso8601', required => 1, coerce => 1);
Fleabite answered 28/2, 2014 at 20:58 Comment(3)
Thanks, this is just the type of solution I was hoping existed.Bromley
My Types::XSD has a built-in Date type constraint. Here's an example coercing from a string. The type is parametrizable, allowing you to use type constraints like Date[minInclusive => '1970-01-01'].Engelhardt
@Engelhardt That is really cool, I am definitely going to go that route, it seems the most flexible without me building something out.Bromley

© 2022 - 2024 — McMap. All rights reserved.