Fix a Moose

It fix the API (yet again) day here in the Moose-Pen

So as we all know I have been playing with the extended operators over the last few posts and I just notices something in my code;

I can enter a mixed case operator like this 'BeETween' and things will still work. This is good but I think I left a part out on the Database::Deriver side of things and in Driver ::DBI I do this;


elsif (uc($predicate->operator) eq Database::Accessor::Driver::DBI::SQL::BETWEEN) {

I uc or upper case that operator and if I take it out

--elsif (uc($predicate->operator) eq Database::Accessor::Driver::DBI::SQL::BETWEEN) {
++elsif ($predicate->operato) eq Database::Accessor::Driver::DBI::SQL::BETWEEN) {

I will obvioulsy fail my test

not ok 3 - Between Operator Params retrieve SQL correct
not ok 4 - Between Operator Params retrieve params correct

Now I am already doing a type check on that operator;

subtype 'Operator',
as 'Str',
where { exists( Database::Accessor::Constants::OPERATORS->{ uc($_) } ) },


in the 'Database::Accessor::Types' class as you can see the 'uc' there but I am not converting the incomming '$_' to uppercase I am just checking to see if it is that 'OPERATORS' constans. Thus when I pass things down to my DAD I get this in the class;

'conditions' => [
bless( {
'predicates' => bless( {
'operator' => 'BETWeeN',


and I am compensating for it with that second 'uc' in Driver::DBI. Not really what I want as I should keep the API constant and treat this like the 'view' on an element, I inherit that from the DA, and 'uc' the operator before it is sent to the DA.

The question is where to do this??

I originally though it would be as easy as just adding a 'coercion' in the types class;


subtype 'Operator',
as 'Str',
where { exists( Database::Accessor::Constants::OPERATORS->{ uc($_) } ) },
message {
"The Operator '$_', is not a valid Accessor Operator!"
. _try_one_of( Database::Accessor::Constants::OPERATORS() );
};

++coerce 'Operator', from 'Str', via { uc($_) };


and then changing my attribute to have a 'coerce';

has operator => (
is => 'rw',
isa => 'Operator',
++ coerce => 1
);

that actually proved to be a dead end as the 'subtype' will override the coercion as it already is a coercion. To make it work and I would have to create a sub-sub type which is a little too much code for what I want.

Next what I tried to do was drop the 'subtype' all together and just make a validating 'coercion' like I did in this post for the gather class;


coerce 'Operator', from 'Str', via {

die "The Operator '$_', is not a valid Accessor Operator!"
. _try_one_of( Database::Accessor::Constants::OPERATORS())
unless(exists( Database::Accessor::Constants::OPERATORS->{ uc($_) } ));
uc($_);
};

however that will not work as I can only use a the above pattern in conjunction with the 'class_type' so I would have to add in this;

class_type 'Operator', { class => 'Str' };

and as we all know there is no such thing a 'String' in perl as ref($_) when $_ is 'BeTEEN' is just 'undef' so for simple types I have to forget about using 'class_type' coercion as they have no class.

In the end I will have to also try and cover this off when I do the drill down for checking the 'parentheses' and 'view' in the '_check_element' sub, and that I think will just bea a simple one line addition like this;


elsif (ref($element) eq 'Database::Accessor::Condition'){
$element->predicates->operator($self->default_operator())
if ( !$element->predicates->operator() );
$element->predicates->operator(uc( $element->predicates->operator));
++ $element->predicates->condition($self->default_condition())

and now of course I have to pull those 'uc' out of Driver::DBI in the few places I have added them, no need to show that here and my tests still run at 100%

However just a little more for today. I went back to '30_where_basic.t' and changed one of the conditions cases to have a mixed case 'condition' value;



operator => '=',
},
{
-- condition => 'AND',
++ condition => 'AnD',
left => {
name => 'last_name',
view => 'people'


sloppy of course but perfectly valid if I allow the same sort of thing on the operator; In the test I now get a fail;

..
ok 10 - Two field conditions create params correct
not ok 11 - Two field conditions retrieve SQL correct
ok 12 - Two field conditions retrieve params correct


another simple two line add in will fix that;

$element->predicates->condition($self->default_condition())
if ( $self->_add_condition>=2 and !$element->predicates->condition() );
$element->predicates->condition(undef)
if ( $self->_add_condition<=1 );
++ $element->predicates->condition(uc( $element->predicates->condition))
++ if ($element->predicates->condition() );
$self->_check_parentheses($element->predicates);

me thinks;

Now I get


..
ok 10 - Two field conditions create params correct
ok 11 - Two field conditions retrieve SQL correct
ok 12 - Two field conditions retrieve params correct


So not much code today but I nipped that API inconstancy in the bud.


dr02-011b.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