Step Back Moose

Its two steps backward day here in the Moose-Pen

I left off yesterday by fixing a bug on the Gather class that allowed you to create a Gather with an empty set of 'elements' like this;

gather => {
        elements => [],
        conditions=>[{
                left => {
                    name => 'last_name',
                },
                right             => { value => 'Bloggings' },
                operator          => '=',
            },]
            },
and that got me wondering if I made the same sort of mistake else where?? The first think I did was review my tests cases for Database::Accessor to see which one used it directly and the first one I found was '20_dad_load.t';

my $da =
  Database::Accessor->new( { retrieve_only => 1, view => { name => 'test' } } );
As one can see I do not have an 'elements' key in the above so first off that is a mistake. I checked my spec and I must of misread it or did not go back to is because is doc clearly states that this should be a required filed. Checking the code I see

has elements => (
            isa => 'ArrayRefofElements',
            is  => 'ro',
            traits  => ['Array'],
            handles => { element_count => 'count',
                         _get_element_by_name  => 'first',
                       },
            default => sub { [] },
        );
and I am missing the 'required' there. I guess I took it out for debugging or testing and never put it back in. I even had a look at the code history on github and I don't see where I ever put that in so I might as well start with that;

has elements => (
            isa => 'ArrayRefofElements',
            is  => 'ro',
            traits  => ['Array'],
            handles => { element_count => 'count',
                         _get_element_by_name  => 'first',
                       },
            default => sub { [] },
++          required=>1,
        );
which is in the 'Database::Accessor::Roles::Common' class. However even with this change I still get a pass on that test which is funny as it should fail; So I tried this;

has elements => (
            isa => 'ArrayRefofElements',
            is  => 'ro',
            traits  => ['Array'],
            handles => { element_count => 'count',
                         _get_element_by_name  => 'first',
                       },
--            default => sub { [] },
          required=>1,
        );
and now I get the expected response;

Attribute (elements) is required at …
Now I fix up that these case these by adding an 'element' array where I need it and I get a full pass. What I have to do now is add three tests one to ensure that 'elements' is required, one to ensure that 'view' is required and a finale one to ensure that 'elements' is not an empty array;

like(
    exception {my $da = Database::Accessor->new( {view => { name => 'test' }} ) },
    qr /Attribute \(elements\) is required at/,
    "Elements is a required Field "
);
like(
    exception { Database::Accessor->new( {elements=>[{ name => 'street', view => 'person', }]} ) },
    qr /Attribute \(view\) is required at /,
    "View is a required Field"
);
like(
    exception {my $da = Database::Accessor->new( {view => { name => 'test' },elements=>[]} ) },
    qr /ArrayRefofElements can not be empty array ref/,
    "Elements cannot be empty array ref"
);
Now I ran the above and got;

ok 51 - Elements is a required Field 
ok 52 - View is a required Field
not ok 53 - Elements cannot be empty
On a side note to make the above work I had to encapsulate the '(' and ')' in my regex, now to look at that empty problem. I will have to go into the 'Database::Accessor::Types' class and look at the ArrayRefofElements sub type;

subtype 'ArrayRefofElements'   => as
  'ArrayRef[Element|Param|Function|Expression]';
Now the above is in the most simple form, fortunately Moose lets us expand this form with the 'where' and 'message' commands. If the 'where' fails then the message will be returned as an error. Like I do in the 'NumericOperator' subtype;

subtype 'NumericOperator', as 'Str', where {
    exists( Database::Accessor::Constants::NUMERIC_OPERATORS->{ uc($_) } );
}, message {
    "The Numeric Operator '$_', is not a valid Accessor Numeric Operato!"
      . _try_one_of( Database::Accessor::Constants::NUMERIC_OPERATORS() );
};
Knowing this I tried this;

subtype 'ArrayRefofElements'   => as
  'ArrayRef[Element|Param|Function|Expression]',
   where { scalar(@{$_})<=0 ? 0 : 1; },
  message {
    "ArrayRefofElements can not be an empty array ref";
  };
which I think worked a little too well as I get this when I run my test;

Attribute (dynamic_sorts) does not pass the type constraint because: ArrayRefofElements can not be empty array ref...
Looking at dynamic_sorts I see it has the ' default' set

        is          => 'rw',
        default     => sub { [] },
        init_arg    => undef,
and looking about I see I have that in a number of places so I just removed those from the few places I found them and I get;

ok 51 - Elements is a required Field 
ok 52 - View is a required Field
ok 53 - Elements cannot be an empty array ref
So that is all fixed up. Good work for today.

IMG_6190a.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