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?
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With