Many Sides of Moose!!

In my last post I did managed to make a little code progress but I still had one major goal to accomplish and that is to make my Data Accessor smart enough that is would know what Driver to use form the connection passed in.

Well I am glad to say I am now able to do that with this test 02_base.t

ok 1 - use DA;
ok 2 - use DA::View;
ok 3 - use DA::Element;
ok 4 - Person is a View
ok 5 - Street is an Element
ok 6 - County is an Element
ok 7 - City is an Element
ok 8 - Address is a DA
ok 9 - SQL correct
ok 10 - Mongo Query correct

Moose is anything but inflexible and with it I was able to come up with a working prototype very quickly just by moving a few things about and reversing my roles.

So before I had DA.pm as a role. I change that to a class
 
– use Moose::Role;
++ use Moose;

–- requires '_execute';
Next I created an new name-space DA::LSD and moved DA::Mongo and DA::SQL into there and made them into roles.
 
– package DA::SQL;
++ package DA::LSD::SQL;

--use Moose;
++use Moose::Role;

and
 
– package DA::Mongo;
++ package DA::LSD::Mongo;

--use Moose;
++use Moose::Role;
Now in DA.pm I am taking advantage of a Moose Util called 'apply_all_roles' with this util I can change the present role of a class on the fly. So by adding this
 
use Moose;
++use Moose::Util qw(apply_all_roles);
and then changing my execute sub a little
 
   my ($conn,$container,$opt) = @_;
   
+   if ($conn eq 'DBH'){
+      apply_all_roles( $self, "DA::LSD::SQL");
+
+  }
+  elsif ($conn eq 'MONGO'){
+     apply_all_roles( $self, "DA::LSD::Mongo");
+
+  }
and presto these two tests work
 
ok(
    $address->retrieve( 'DBH', $result ) eq
      'SELECT  street, city, country FROM person  AS me',
    'SQL correct'
);
ok(
    $address->retrieve('MONGO') eq
      'db.person.find({},{ street: 1, city: 1, country: 1}',
    "Mongo Query correct"
);

I will have fix the above check for the real objects but the stub is just fine for now.

I was a little afraid that I would not longer be able to enforce my API because I had to drop out the "requires '_execute" bit out of DA.pm but Moose let me have that as well.

All I need to do is create another role
 
package DA::Roles::API;
use Moose::Role;
requires '_execute';
1;
where I can add in all the required parts of my API and then just apply that role to my DA::LSDs like so
 
package DA::LSD::Mongo;
with qw(DA::Roles::API);

package DA::LSD::SQL;
with qw(DA::Roles::API);
and all is good. I can even force the DA::LSDs to have use that role by utilizing another moose util called does_role in my retrieve sub like this
 
die "LSD $conn must use DA::Roles::API"
    if (!does_role($self,'DA::Roles::API'));
and the code will die if that Role is not applied

Now I am going to have to spend some time looking deeper into this as it seems a little too easy. I will have to check if both roles are applied at the same time and if they stick around and what happens when I call the apply more than once, and I still have that problem of the 'sub SQL' in Element and View, but still neat to see that it works.


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