Baby Moose Grows Strong

Back to Accessor.pm day here in the Moose-Pen.

Starting where I left off in my last post I needed to figure out some way to get the raw query results back from Accessor.pm. I gave this a little though as there are a number of things to consider. First I never want to expose the underlying DAD to the end user of Accessor.pm, Second I have to make the name of call generic in the same way the CRUD calls are. Finally as I see this used largely for debugging it should return more than just a string.

To address the three above I started with an new sub called 'raw_query' ;


sub raw_query {
my $self = shift;
my ($conn, $type) = @_;

$self->_try_one_of(Database::Accessor::Constants::OPERATORS)
unless (exists( Database::Accessor::Constants::OPERATORS->{ uc($type) } ));

my $drivers = $self->_ldad();
my $driver = $drivers->{ ref($conn) };
die "$type No Database::Accessor::Driver loaded for "


and the I quickly saw I was getting into anti-pattern territory as the code after 'my $drivers' is the same block as found in 'sub _execute' therefor I had to re-factor a little before I wen too far and this is what I now have

private_method _execute => sub {
my $self = shift;
my ( $type, $conn, $container, $opt ) = @_;
my $dad = $self->_get_dad($conn);
$dad->execute( $type, $conn, $container, $opt );
return $container;

};
# DADNote: The DAD will have to have the same function call 'raw_query' with one param ($type) CRUD return a string representation of the query.
sub raw_query {
my $self = shift;
my ($conn, $type) = @_;

$self->_try_one_of(Database::Accessor::Constants::OPERATORS)
unless (exists( Database::Accessor::Constants::OPERATORS->{ uc($type) } ));

my $dad = $self->_get_dad($conn);
my $raw = $dad->raw_query(uc($type));
my $hash = {DAD=>ref($dad),
query=>$raw};
return $hash;
}

private_method _get_dad => sub {
my $self = shift;
my ($conn) = @_;
my $drivers = $self->_ldad();
my $driver = $drivers->{ ref($conn) };
die "No Database::Accessor::Driver loaded for "
. ref($conn)
. " Maybe you have to install a Database::Accessor::Driver::?? for it?"
unless ($driver);

my $dad = $driver->new(
{
view => $self->view,
elements => $self->elements,
dynamic_elements => $self->dynamic_elements,
conditions => $self->conditions,
dynamic_conditions => $self->dynamic_conditions,
links => $self->links,
dynamic_links => $self->dynamic_links,
gathers => $self->gathers,
dynamic_gathers => $self->dynamic_gathers,
filters => $self->filters,
dynamic_filters => $self->dynamic_filters,
sorts => $self->sorts,
dynamic_sorts => $self->dynamic_sorts,
}
);
return $dad;
};


Ok quite a few changes thrown in there.

The first thing I did was I imported a new MooseX called 'MooseX::Privacy' which lets me mark the '_get_dad' sub as a private method so some smarty pants can't read my code and then get a DAD directly by doing this;


my $dad=$some_da->_get_dad($dbh);

I also did the same for '_execute' and I may add in some more later. So that is requirement one, never expose the underlying DAD, the second requirement a simple generic name as 'raw_query' is about as plain as it gets, and for the third requirement I return a hash-ref with both the query and the DAD type.

You will also note some other little things. I added in a #DADNote to remind me to add to to the DAD writers guide and that I am using;


$self->_try_one_of(

and this is coming from 'Database::Accessor::Types' which I import at the beginning, one of the nice Moose bits is my Types class is just a Role and I have access to all it contains like any other Role.

Next I have to adjust my 'Database::Accessor::Roles::Driver' a little like this


requires 'execute';
++ requires 'raw_query';

and I should be good to go, but I need a test case for this or at least test it someplace I think 20_dad_load.t is the best spot, and I think this;

foreach my $type (qw(Create retrieve UPDATE DeLeTe)){
my $raw = $da->raw_query(Data::Test->new(),$type);
ok($raw->{DAD} eq 'Database::Accessor::Driver::Test','correct raw DAD class');
ok($raw->{query} eq uc($type).' query','correct '.uc($type)." raw query returned");
}

will do. I will also have to update my 'Database::Accessor::Driver::Test' to work with the changes to the Driver Role and the above test and this is what I added in;

sub raw_query {
my $self = shift;
my ($type) = @_;
return $type.' query',
}

and I run my tests (after a little debugging and correcting the # of tests run) I get


ok 44 - DA is a Database::Accessor
ok 45 - correct raw DAD class
ok 46 - correct CREATE raw query returned
ok 47 - correct raw DAD class
ok 48 - correct RETRIEVE raw query returned
ok 49 - correct raw DAD class
ok 50 - correct UPDATE raw query returned
ok 51 - correct raw DAD class
ok 52 - correct DELETE raw query returned

and to be thorough I ran the full test suite with this result

All tests successful.
Files=26, Tests=325, 37 wallclock secs ( 0.19 usr 0.06 sys + 34.75 cusr 2.02 csys = 37.02 CPU)
Result: PASS

So looks like I am ready to go back and play with my Driver::DBI tomorrow.

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