Moose Loose Ends Part the XII

Well its fix one break everything day here in the Moose-Pen

I thouhg it was just going to be one of those quick look how well things pass postette days today but I was dead wrong;

I did a check in a a quick push and then ran the full test suite and got


t/20_dad_load.t ............. Attribute (conditions) does not pass the type constraint because: ArrayRefofConditions can not be an empty array ref at /usr/local/lib/perl/5.18.2/Moose/Object.pm line 24
Moose::Object::new('Database::Accessor', 'HASH(0x2eeb320)') called at t/20_dad_load.t line 15
# Looks like your test exited with 255 before it could output anything.

So many times I just had to kill the run.

I am about 99.99756% sure it was this cnage from yeaterday


subtype 'ArrayRefofConditions' => as 'ArrayRef[Condition]',
where { scalar(@{$_})<=0 ? 0 : 1; },
message {
"ArrayRefofConditions can not be an empty array ref";
};

that is causeing my problems. Now if I do revert this one I sill have the problem that I was trying to solve, 'conditions' on a link is a required field.

Well the fix is quite simple I just create another 'subtype' and in this type I can even give it a very specific error message;


subtype 'LinkArrayRefofConditions' => as 'ArrayRef[Condition]',
where { scalar(@{$_})<=0 ? 0 : 1; },
message {
"conditions can not be an empty array ref";
};

subtype 'ArrayRefofConditions' => as 'ArrayRef[Condition]';


all I need to do now plug it into in 'Links' class in Accesspr.pm

has conditions => (
-- isa => 'ArrayRefofConditions',
++ isa => 'LinkArrayRefofConditions',
required=> 1,
is => 'ro',
traits => ['Array'],
handles => { condition_count => 'count', },
# default => sub { [] },
documentation => "links"
);

My error result is now

# 'links->conditions' Constraint: conditions can not be an empty array ref!

I do get a pass now in '42_new_validation.t' but '20_dad_load.t' fails hard with this error;

Can't use an undefined value as an ARRAY reference at \GitHub\database-accessor\lib/Database/Accessor.pm

So again fix one break another!!

It did take a little digging but it was a simple fix;


has dynamic_conditions => (
isa => 'ArrayRefofConditions',
traits => ['Array','MooseX::MetaDescription::Meta::Trait'],
description => { not_in_DAD => 1 },
is => 'rw',
++ default => sub { [] },
init_arg => undef,
handles => {
reset_conditions => 'clear',
add_condition => 'push',
dynamic_condition_count => 'count',
},
);

I had taken that 'default' out the other day all I needed to do was add it back in. Once done I now ran into another bug

...
not ok 86 - Elements is a required Field
not ok 87 - View is a required Field


This time the debugging was made much more simple because my error message was

Failed test 'View is a required Field'
at 20_dad_load.t line 149.
'Database::Accessor new Error:
The following Attribute is required: (view)

With constructor hash:
{
'elements' => [
{
'view' => 'person',
'name' => 'street'
}
]
}
at 20_dad_load.t line 148'

rather than what I had coded

Attribute \(view\) is required at \GitHub\database-accessor\lib/Database/Accessor.pm line 233...

All I had to do was change the exception string and I had a full pass at least on that test case.

Running the full suite I got a little better results this time with only 7 tests cases failing rather than 20+ on the first run;

The next bug was a little odd as it was in '11_link.t' at the very start


my $link = Database::Accessor::Link->new(
{
type => 'left',
to => { name => 'test' },
conditions => [
{
left => {
name => 'field-1',
view => 'table-1'
},
right => {
name => 'field-2',
},
operator => '='
}
]
}
);

which should pass but I was getting;

Attribute (conditions) does not pass the type constraint because: conditions can not be an empty array ref! At …

The source of this error is trusting that your code change is ok when you are testing for a fail. '42_new_validation.t' worked fine so I figured the rest was ok. It wasn't. I forgot to add in a 'coerce' call for my sub-type 'LinkArrayRefofConditions' and therefore I was getting the error.

Now the nifty Moose part. I was faces with having some duplicated code as the 'coerce' for both of the sub-types is the same. All I needed to do was this patch to get both


--coerce 'ArrayRefofConditions', from 'ArrayRef', via {
-- return _predicate_array_or_object( "Database::Accessor::Condition", $_ );
--}, from 'HashRef', via {
-- return [ Database::Accessor::Condition->new( { predicates => $_ } ) ];
--};

foreach my $subtypes (qw(LinkArrayRefofConditions ArrayRefofConditions )) {
coerce $subtypes, from 'ArrayRef', via {
return _predicate_array_or_object( "Database::Accessor::Condition",
$_ );
}, from 'HashRef', via {
return [ Database::Accessor::Condition->new( { predicates => $_ } ) ];
};
}


and now that test passes. Then went a little mad and did the same change to a few other 'sub-types' that shared the same 'coerce' pattern.

I reran my test suite and now I finally get a full pass.

Well almost I still had to clean up on test count.

stanmoose.jpg

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations