Moose Police Get out of My Dreams
Well the Moose-Pen is not dead yet as I still found some Moose to blog about, and I though I was so close.
On thing that really bugs me about Perl is the fact you can have a lovely interface like this
my $thingy = $object->get_some_thing();
$object->set_some_thing(“Not my thing”);
and then some smarty-pants RFB comes by and does this
my $thingy = $object->{some_thing};
$object->{some_thing} = 'Not my thing';
Anyone who ever comes from a OO background say in Java or even C# usually can be heard screaming into the halls of a Perl shop cursing the very day Larry said “let's create some disruption” and have 'c' with types.
Well lets not say every one who come fror the OO world to Perl has this reaction. I still remember playing with Stack peek and and if memory servers me correctly push. I did piss a few of the Java guys off by using that little gem every once and a while as a shortcut.
Anyway back to Perl as most of us know the OO part of Perl is largely an afterthought stuck in there to most likely solve a problem someone was working on at the time. So you will allays will be able to get back to Perl's script roots thought this back door.
Now one of the reasons for choosing Accessor is that is offers the opportunity to have a very tight coding window around your Data Base. You can lock the DB down access to only what you want without all the overhead of an Authorization system.
Now the little trick you see in the first lines of this post will unravel this lock down as I could easily take a class that returns an Accessor with the 'retrieve_only' flag set. Then it is one simple line in my code to flip that to off and I can start adding records or deleted them.
Well Moose has a cure for that. I blundered upon MooseX::AccessorsOnly a few months ago and I knew I would find a use for it. Though to me I was a little weary as it has no tests little documentation or examples and the creator openly warns you the code it slow. No speed in not an issue for Accessor as the DB end will always be the slowest part and despite not tests or docs it was easy to figure out so onward and upward.
What this MooseX does it call a function each time an underlying Perl variable that has a Moose accessor associated with it is modified or accessed. The first thing to do is add;
use MooseX::MetaDescription;
++ use MooseX::AccessorsOnly;
use Carp;
to my Accessor package and then in the BUILD sub all I add is this call
my %saved = %$self;
tie(
%$self,
"MooseX::AccessorsOnly",
sub {
my ( $who, $how, $what ) = @_;
die
"Attempt to access Database::Accessor::$what directly at $who!";
}
);
%$self = %saved;
So what is going on here. I first copy my present instance state ($self) into a hash then using the tie command I bin that though to the ' MooseX::AccessorsOnly' class which does all sorts of majik in the back ins and I also pass in a sub that will be called if some-one tries to change or even access one of my Accessor attributes.
So a quick test of this lets say in 30_view.t for now
eval {
my $test = $da->{view}
};
if ($@){
pass("Cannot access attribute directly");
}
else {
fail("Cannot access attribute directly");
}
eval {
$da->{view} ='something';
};
if ($@){
pass("Cannot change attribute directly");
}
else {
fail("Cannot change attribute directly");
}
rerun my test and get
…
ok 3 - DAS View is correct
ok 4 - Cannot access attribute directly
ok 5 - Cannot change attribute directly
ok 6 - View is Required
…
And the MooseX police saves the day.
These articles