Sophisticated Moose

Today in the Moose-pen I am going to play with the very familiar 33_condtions.t and this time I am going to solve another little API problem I know I am going to run into.

Part of my evil plan is to allow end users to add in conditions on the fly and I have made provision for that with the 'rw' 'conditions' attribute found on my DAD Role. Now I have to fix a minor oversight on my part can change the type on 'conditions' to be the same as the original in Accessors, so I changed this

– isa => 'ArrayRefofPredicates',
++ isa => 'ArrayRefofConditions',

What I want to be able to do is allow my end users to do something like this

my $da = Database::Accessor->new($in_hash2);
$da->DAD->add_condition({left =>{name =>'country',
view =>'People'},
right =>{value=>'Slyvania'},
operator =>'=',
condition =>'AND'});

In this case had in just a single Hash-Ref conditions not an array ref. Now I have learned years of programming that a good chunk of the quires I have done had only a single condition. For example in one project I just completed I have about ninety SQL queries, (excluding the dedicated search part of the site) of these almost half forty-two had only a single param. As I like to make things simple for my end users allowing one to enter an Array-Ref or a singleton Hash-Ref is a real benefit.

Moose makes setting up this type of multi-coercion a simple affair. All I need to do is revisit my again and 'extend' the 'ArrayRefofConditions ' coercion by dropping the '};' and replace it with a '},' and then adding the new coercion;

– };
++ from 'HashRef', via {
++ my $objects = [];
++ push( @{$objects}, Database::Accessor::Condition->new({predicates=>[$_]}) );
++ return $objects;
++ };

This time I am telling Moose what to do when it encounters a HashRef on the 'Conditions' param. Then is is a simple matter to return just one Constion class in an Array.

Now I just add this to my test case

my $in_hash3 = {
view => {name => 'People'},
elements => [{name => 'first_name',
view =>'People' },
{name => 'last_name',
view => 'People' },
{name => 'user_id',
view =>'People' } ],
conditions=>{left =>{name =>'last_name',
view =>'People'},
operator =>'=',
open_parenthes =>1,
condition =>'AND',
my $da2 = Database::Accessor->new($in_hash3);
ok(ref($da2->conditions()->[0]) eq "Database::Accessor::Condition",'DA has a condtion');
ok(scalar(@{$da2->conditions()}) == 1,'DA has only 1 condtion');
ok(scalar(@{$da2->conditions()->[0]->predicates}) == 1,'DA has only 1 predicate');
ok(ref($da2->conditions()->[0]->predicates->[0]) eq "Database::Accessor::Predicate",'DA has a condtion predicate is a predicate');

re-run my test case and get;
ok 7 - DA has a condtion
ok 8 - DA has only 1 condtion
ok 9 - DA has only 1 predicate
ok 10 - DA has a condtion predicate is a predicate

Sophisticated no?


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