Okay, so MooseX::Role::BuildInstanceOf is not one of my modules. And while I submited the patch, the feature itself was born out of fREW‘s DBIx::Class::DeploymentHandler. So, in all this, my role was at best to be the pollinator agent between two beautiful flowers. But, hey, it’s not like a little bit of noise is going to hurt any of the involved parties, sooo… let’s see what the buzz’s about.
Insanely Quick Intro to MooseX::Role::BuildInstanceOf
MooseX::Role::BuildInstanceOf is a Moose module that aims at reducing the amount of boilerplate code needed for dealing with sub-objects. It’s a little meta-scary at first, but once one understanding settles in, it’s humongously handy. Without going into the details, with that module, you can turn that chunk of code:
package MyShip; use Moose; has engine => ( is => 'ro', lazy_build => 1, ); has engine_args => ( isa => 'ArrayRef', is => 'ro', ); sub build_engine { my $self = shift; return MyShip::Engine->new( @{ $self->engine_args || [ fuel => 100 ] }, max_speed => 10, ); } 1;
into
package MyShip; use Moose; with 'MooseX::Role::BuildInstanceOf' => { target => '::Engine', args => [ fuel => 100 ], fixed_args => [ max_speed => 10 ], }; 1;
Both versions will do just what you think it will do when you write
# damned Ferengies never fill up the tank my $warbird = MyShip->new( engine_args => [ fuel => 20 ] );
There is a lot more to MooseX::Role::BuildInstanceOf than that, but we can agree that it’s already pretty sweet.
So, What’s New?
In the last few days, I’ve been deep-diving into DBIx::Class::DeploymentHandler. Within that distribution, fREW kinda rolled out a module similar to MooseX::Role::BuildInstanceOf: DBIx::Class::DeploymentHandler::WithApplicatorDumple. It is acknowledged in the source of the module that its implementation is a little on the ghetto side, and should probably be refactored with Role::subsystem or, ah AH!, MooseX::Role::BuildInstanceOf.
Me, eternal meddler, couldn’t resist looking into that, and quickly saw that WithApplicatorDumple
had something that MX::R::BIO
was missing: the ability to automatically push down to the sub-objects some attributes of the main object. Very handy, that. So I cracked my knuckles, went to work… and by now the code
package MyShip; use Moose; has captain => ( is => 'ro' ); has intercom => ( is => 'ro', isa => 'Log::Dispatchouli', default => sub { ... }, ); has coordinates => ( is => 'ro', isa => 'MyShip::Coord', default => sub { MyShip::Coord->new( 0, 0 ); }, ); has engine => ( is => 'ro', lazy_build => 1, ); has engine_args => ( isa => 'ArrayRef', is => 'ro', ); sub build_engine { my $self = shift; return MyShip::Engine->new( @{ $self->engine_args || [ fuel => 100 ] }, max_speed => 10, coordinates => $self->coordinates, bridge_monkey => $self->captain, intercom => $self->intercom->proxy({ proxy_prefix => 'Engine' }); ); } 1;
can all be replaced by
package MyShip; use Moose; has captain => ( is => 'ro' ); has intercom => ( is => 'ro', isa => 'Log::Dispatchouli', default => sub { ... }, ); has coordinates => ( is => 'ro', isa => 'MyShip::Coord', default => sub { MyShip::Coord->new( 0, 0 ); }, ); with 'MooseX::Role::BuildInstanceOf' => { target => '::Engine', args => [ fuel => 100 ], fixed_args => [ max_speed => 10 ], inherited_args => [ 'coordinates', { bridge_monkey => 'captain', intercom => sub { my $self = shift; $self->intercom->proxy({ proxy_prefix => 'Engine' }); }, } ], }; 1;
Nifty, isn’t?
No comments