NAME
MooseX::ConstructInstance - small wrapper method for instantiating helper objects
SYNOPSIS
This role consists of a single method:
sub construct_instance {
my (undef, $class, @args) = @_;
$class->new(@args);
}
(Actually, since 0.006, it's a little more complex.)
DESCRIPTION
Normally you would build an LWP::UserAgent something like this:
sub _build_ua {
my $self = shift;
LWP::UserAgent->new(...);
}
Following the principles of dependency injection, you may prefer not to hard-code the class name (see also MooseX::RelatedClasses):
has ua_class => (is => 'ro', default => 'LWP::UserAgent');
sub _build_ua {
my $self = shift;
$self->ua_class->new(...);
}
This module allows you to take it to a further level of abstraction:
has ua_class => (is => 'ro', default => 'LWP::UserAgent');
sub _build_ua {
my $self = shift;
$self->construct_instance($self->ua_class, ...);
}
Why? What benefit do we accrue from constructing all our helper objects via a seemingly redundant object method call? How about this:
{
package Authentication;
use Moose::Role;
around construct_instance => sub {
my ($orig, $self, $class, @args) = @_;
my $instance = $self->$orig($class, @args);
if ($instance->DOES('LWP::UserAgent')) {
$instance->credentials('', '', 'username', 'password');
}
return $instance;
};
}
Moose::Util::ensure_all_roles($something, 'Authentication');
Now whenever $something
constructs an LWP::UserAgent object, it will automatically have authentication credentials supplied.
MooseX::ConstructInstance can be used to apply policies such as:
If
$foo
has adbh
attribute, and it constructs an object$bar
, then$bar
should inherit$foo
's database handle.All node objects must be have "backlinks" to the parent node that created them.
Despite the name, MooseX::ConstructInstance is actually a Moo::Role. You can apply MooseX::ConstructInstance to Moose classes using:
package MyClass;
use Moose;
with qw( MooseX::ConstructInstance );
You can apply it to Moo classes using:
package MyClass;
use Moo;
with qw( MooseX::ConstructInstance );
You can apply it to other classes using:
package MyClass;
use MooseX::ConstructInstance -with;
As of version 0.006 of MooseX::ConstructInstance, $class
may be a coderef or a blessed object overloading &{}
. The construct_instance
method acts a bit like this:
sub construct_instance {
my (undef, $class, @args) = @_;
if ( is_codelike($class) ) {
return $class->(@args);
}
else {
$class->new(@args);
}
}
FAQ
What if I need to use a constructor which is not called new
?
Aye; there's the rub.
For now, this works, though it's not an especially elegant solution...
sub _build_document {
my $self = shift;
local $MooseX::ConstructInstance::CONSTRUCTOR = 'new_from_file';
$self->construct_instance($self->document_class, ...);
}
BUGS
Please report any bugs to http://rt.cpan.org/Dist/Display.html?Queue=MooseX-ConstructInstance.
SEE ALSO
Moose, MooseX::RelatedClasses.
AUTHOR
Toby Inkster <tobyink@cpan.org>.
COPYRIGHT AND LICENCE
This software is copyright (c) 2012-2013 by Toby Inkster.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
DISCLAIMER OF WARRANTIES
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.