package Bread::Board::Declare::Meta::Role::Attribute::Container;
BEGIN {
$Bread::Board::Declare::Meta::Role::Attribute::Container::AUTHORITY = 'cpan:DOY';
}
{
$Bread::Board::Declare::Meta::Role::Attribute::Container::VERSION = '0.15';
}
use Moose::Role;
Moose::Util::meta_attribute_alias('Container');
# ABSTRACT: attribute metarole for container attributes in Bread::Board::Declare
use Class::Load 'load_class';
has dependencies => (
is => 'ro',
isa => 'Bread::Board::Service::Dependencies',
coerce => 1,
predicate => 'has_dependencies',
);
after attach_to_class => sub {
my $self = shift;
my $tc = $self->type_constraint;
if ($tc && $tc->isa('Moose::Meta::TypeConstraint::Class')) {
load_class($tc->class);
confess "Subcontainers must inherit from Bread::Board::Container"
unless $tc->class->isa('Bread::Board::Container');
}
else {
confess "Attributes for subcontainers must specify a class type constraint";
}
};
around get_value => sub {
my $orig = shift;
my $self = shift;
my ($instance) = @_;
return $self->$orig($instance)
if $self->has_value($instance)
|| $self->has_default
|| $self->has_builder;
my $val = $instance->get_sub_container($self->name);
if ($self->has_type_constraint) {
$val = $self->type_constraint->coerce($val)
if $self->should_coerce;
$self->verify_against_type_constraint($val, instance => $instance);
}
return $val;
};
around _inline_instance_get => sub {
my $orig = shift;
my $self = shift;
my ($instance) = @_;
return 'do {' . "\n"
. 'my $val;' . "\n"
. 'if (' . $self->_inline_instance_has($instance) . ') {' . "\n"
. '$val = ' . $self->$orig($instance) . ';' . "\n"
. '}' . "\n"
. 'else {' . "\n"
. '$val = ' . $instance . '->get_sub_container(\'' . $self->name . '\');' . "\n"
. join("\n", $self->_inline_check_constraint(
'$val',
'$type_constraint',
'$type_message',
)) . "\n"
. '}' . "\n"
. '$val' . "\n"
. '}';
};
no Moose::Role;
1;
__END__
=pod
=head1 NAME
Bread::Board::Declare::Meta::Role::Attribute::Container - attribute metarole for container attributes in Bread::Board::Declare
=head1 VERSION
version 0.15
=head1 DESCRIPTION
This attribute trait indicates that the attribute (in a
L<Bread::Board::Declare> class) contains a subcontainer rather than a service.
It must be specified explicitly (or else a service that happens to return a
container will be created):
has attr => (
traits => ['Container'],
is => 'ro',
isa => 'Bread::Board::Container',
);
Container attributes (unlike service attributes) can have defaults and
builders, allowing you to also define subcontainers inline when desired, as in:
has attr => (
traits => ['Container'],
is => 'ro',
isa => 'Bread::Board::Container',
default => sub {
container Foo => as {
service Bar => 'BAR';
};
}
);
=head1 ATTRIBUTES
=head2 dependencies
If no default or builder is supplied, the type constraint will be used to
create a container instance automatically (using a temporary
L<ConstructorInjection|Bread::Board::ConstructorInjection> service). This is
the dependency specification to use for that temporary service.
=head1 AUTHOR
Jesse Luehrs <doy@tozt.net>
=head1 COPYRIGHT AND LICENSE
This software is Copyright (c) 2013 by Jesse Luehrs.
This is free software, licensed under:
The MIT (X11) License
=cut