[Melbourne-pm] Moose - complex validation

Ryan, Martin G Martin.G.Ryan at team.telstra.com
Tue Jan 19 23:09:17 PST 2010

Hi Scott !

[ Warning: I don't know Moose for any reasonable definition of "know".  I've just been
  reading a lot about it lately and can't resist a stab.  Sorry for using your genuine
  predicament as a testing toy ]

> I have a complex moose validation, dependent on multiple inputs.

> subtype 'Command'
> 	=> as Str,
> 	# XXX how to get root ?
>	=> where { -f "$root/$_" && -x "$root/$_" },
>	=> message { "Command provided does not exist or is not executable " };

> has 'script' => (
>	is => 'ro',
>	isa => 'Command',
>	required => 1,
> );

It seems to me that subtypes are more for declaring "reduced domain types".
If you can't innately define whether a value is part of your type - i.e. using nothing
other than the value itself - then subtypes is the wrong place for it.

In your case, if I supply you "rebootWithMalice" as a script value, you cant
tell me if it passes muster as a member of the "Command" subtype without interrogating
the perfectly innocent, by-standing, "root" attribute.  You really want to do a 
validation of your script attribute but only after the root attribute
has been set (or declined to be set in favour of a default).

Looking at Moose::Manual::Attribute under "Default and builder methods", it covers
using a sub as a default value or declaring a "builder" routine but its all aimed at
bringing the value into existence from nothing rather than validating what's supplied.

Looking at Moose::Manual::Construction ...

== snip ==
     The "BUILD" method is called after an object is created.
     There are several ways to use a "BUILD" method. One of the
     most common is to check that the object state is valid.
     While we can validate individual attributes through the use
     of types, we can't validate the state of a whole object that
== snip ==

As you already alluded to, I think this is what you're really doing.
Your validating one attribute but its validity is dependant on another
so, we're really talking about validating the thing as a whole.

Your other alternatives AFAICT, is BUILDARGS where you can do the
checks on the parameter list as supplied but as the object is not
created yet, you want have that default for root available to you; and
using a trigger which seems to me more aimed at attributes who's value
change during the life of the object and need to be revalidated (presumably 
your only after the one-time validation at creation time).

So, if your question is "does BUILD seem the right place?", it
would have my vote, FWIW.

-----Original Message-----
From: melbourne-pm-bounces+martin.g.ryan=team.telstra.com at pm.org [mailto:melbourne-pm-bounces+martin.g.ryan=team.telstra.com at pm.org] On Behalf Of Scott Penrose
Sent: Wednesday, 20 January 2010 4:26 PM
To: Melbourne Perlmongers
Subject: [Melbourne-pm] Moose - complex validation

Hey Team

I have a complex moose validation, dependent on multiple inputs.


package MyThing;
use Moose;

subtype 'Path'
	=> as Str
	=> where { -d $_ }
	=> message { "Path provided must exist" };

subtype 'Command'
	=> as Str,
	# XXX how to get root ?
	=> where { -f "$root/$_" && -x "$root/$_" },
	=> message { "Command provided does not exist or is not executable " };

had 'root' => (
	is => 'ro',
	isa => 'Path',
	default => '/usr/bin',

has 'script' => (
	is => 'ro',
	isa => 'Command',
	required => 1,

Basically you would create the object

my $o = MyThing->new(
	script => 'example',

but you could override the default root for the scripts with:

my $o = MyThing->new(
	script => 'example',
	root => '/usr/sbin',

So... as you can see form the subtype 'Command' I am not sure how you can access the other parameter, and to define the validation order, as root would need to be done first.

So... should it be done in a BUILD ?

sub BUILD {
	my $self = shift;
	if (! -x $self->root . '/' . $self->script) {
		die "Help... script should exist in path and be executable...";

I.e. is 'subtype' only for primitives ?

Melbourne-pm mailing list
Melbourne-pm at pm.org

More information about the Melbourne-pm mailing list