Moose Show off

Today in the Moose-Pen I am going to cleanup up more Moose droppings. Now I already added in the Function and Expression class and came up with a few modest tests case for them '19_function_expression.t'.

Not that is fine and good for a unit test on that class but the problem is these two classes will never be used as stand alone classes they will always be used inside other objects typically in the same place I would use a Param or Element class and most of the time in a Predicate object.

The best place to basic unit tests of both Function and Expression is in the predicate unit tests case '14_predicate.t' so in there I add firsts added;


my $function_1_param = {left=> {name=>'left'},
right=>{function => 'substr',
left => {name=>'test'},
right => { param => 3 },
}};
ok(Database::Accessor::Predicate->new($function_1_param),"Function with 1 param works");

So in this case the test will fail with this

Attribute (name) is required at C:\D

as I do not have a coerce for a 'Function' on that Predicate 'right' attribute. So I will have to do this in my Database::Accessor::Roles::Comparators role

-- isa => 'Element|Param',
++ isa => 'Element|Param|Function',

and then in my types a the same old patten once again use the class, and add in the 'Function' class_type then I will have to change my “Element' coerce to this

coerce 'Element', from 'HashRef', via {
++ if (exists($_->{function})){
++ Database::Accessor::Function->new( %{$_} );
++ }
++ elsif (exists($_->{value}) || exists($_->{param})){
-- if (exists($_->{value}) || exists($_->{param})){

and now my test passes
ok 6 - Function with 1 param works

Well that is one part of the story the sad thing is we can have many params on a function like this

my $function_multi_param = {left=> {name=>'left'},
right=>{function => 'substr',
left => {name=>'test'},
right =>[ { param => 3 },
{ param => 2 }],
}};

ok(Database::Accessor::Predicate->new($function_multi_param),"Function with multi param works");


So I will have to take that into account. So the while rigmarole again this time to add in the 'ArrayRefofParams' and once I added in all the type stuff I get my tests passing
ok 6 - Function with 1 param works
ok 7 - Function with multi param works


This is programming so my problems are far from over as this is valid as well;

my $function_mixed_right= {left=> {name=>'left'},
right=>{function => 'substr',
left => {name=>'test'},
right =>[ { name=>'test',
view=>'table1' },
{ param => 2 }],
}};

and so I have to take a different tack on my coercion as in the above I might pass my first test but if I dig a little deeper hat I have are two Params classes not a Element and a Param as this ;

ok(ref($predicate->right()->right->[0]) eq 'Database::Accessor::Element',"My frist right is an Element");
ok(ref($predicate->right()->right->[1]) eq 'Database::Accessor::Param',"My frist right is a Param");

fails like this;
ok 9 - Function with mixed params works
not ok 10 - My frist right is an Element
ok 11 - My frist right is a Param

So I add in the ' ArrayRefofElements' on the isa

-- isa => 'Element|Param|Function|ArrayRefofParams',
++ isa => 'Element|Param|Function|ArrayRefofParams|ArrayRefofElements',

How ever I am going to run into the same problems I had before if I swap the last two. it will work but for Elements but fail for Params. That is not very practical, so I need a little re-factor on my coercion a like this;

coerce 'ArrayRefofParams', from 'ArrayRef', via {
_right_left_coerce($_);
};

coerce 'ArrayRefofElements', from 'ArrayRef', via {
_right_left_coerce($_);
};

sub _right_left_coerce {
my ($in) = @_;
my $objects = [];
foreach my $object (@{$in}) {
push( @{$objects}, _element_coerce($object));
}
return $objects
}

sub _element_coerce {
my ($hash) = @_;
my $object;
if (exists($hash->{function})){
$object = Database::Accessor::Function->new( %{$hash} );
}
elsif (exists($hash->{value}) || exists($hash->{param})){
$object = Database::Accessor::Param->new( %{$hash} );
}
else{
$object = Database::Accessor::Element->new( %{$hash} ) ;

}
return $object;
}


and what the above will give me is this error

Attribute (right) does not pass the type constraint because: Validation failed for 'ArrayRefofElements|
ArrayRefofParams|Element|Function|Param' with value [ { name: "right_1", view: "table1" }, { param:
"right_2" } ] at C:\Dwimperl\perl\site\lib\Moose\Meta\Attribute.pm line 517

until I fix it with a slight change to my subtypes

– subtype 'ArrayRefofElements' => as 'ArrayRef[Element]';
++ subtype 'ArrayRefofElements' => as 'ArrayRef[Element|Param|Function]';

– subtype 'ArrayRefofParams' => as 'ArrayRef[Param]';
++ subtype 'ArrayRefofParams' => as 'ArrayRef[Param|Element|Function ]';


to include the missing Database::Accessor classes and presto;

ok 6 - Function with 1 param works ok 7 - right is a function ok 8 - Function with multi params works ok 9 - Function with mixed params works ok 10 - My frist right is an Element ok 11 - My frist right is a Param
Really does show off how good Moose is at types;

df40fbac24bbbb799d39e35233ec9813--cute-baby-animals-wild-animals.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