From e1c675f0a434b6323cff812c8293eee5dc0c6c28 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Mon, 10 Oct 2011 14:10:14 -0500 Subject: sketch out subcontainers (still needs work) --- lib/Bread/Board/Declare/Meta/Role/Attribute.pm | 11 ++-- .../Board/Declare/Meta/Role/Attribute/Container.pm | 75 ++++++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 lib/Bread/Board/Declare/Meta/Role/Attribute/Container.pm (limited to 'lib/Bread/Board/Declare/Meta') diff --git a/lib/Bread/Board/Declare/Meta/Role/Attribute.pm b/lib/Bread/Board/Declare/Meta/Role/Attribute.pm index d356e3a..7a08376 100644 --- a/lib/Bread/Board/Declare/Meta/Role/Attribute.pm +++ b/lib/Bread/Board/Declare/Meta/Role/Attribute.pm @@ -5,6 +5,9 @@ use Moose::Role; use List::MoreUtils 'any'; use Moose::Util 'does_role', 'find_meta'; +use Bread::Board::Declare::Meta::Role::Attribute::Container; +use Bread::Board::Declare::Meta::Role::Attribute::Service; + =attr service Whether or not to create a service for this attribute. Defaults to true. @@ -28,14 +31,14 @@ around interpolate_class => sub { return $class->$orig(@_) if $options->{metaclass}; - if (exists $options->{service} && !$options->{service}) { - return $class->$orig(@_); - } + return $class->$orig(@_) + if exists $options->{service} && !$options->{service}; my ($new_class, @traits) = $class->$orig(@_); return wantarray ? ($new_class, @traits) : $new_class - if does_role($new_class, 'Bread::Board::Declare::Meta::Role::Attribute::Service'); + if does_role($new_class, 'Bread::Board::Declare::Meta::Role::Attribute::Service') + || does_role($new_class, 'Bread::Board::Declare::Meta::Role::Attribute::Container'); my $parent = @traits ? (find_meta($new_class)->superclasses)[0] diff --git a/lib/Bread/Board/Declare/Meta/Role/Attribute/Container.pm b/lib/Bread/Board/Declare/Meta/Role/Attribute/Container.pm new file mode 100644 index 0000000..90d027d --- /dev/null +++ b/lib/Bread/Board/Declare/Meta/Role/Attribute/Container.pm @@ -0,0 +1,75 @@ +package Bread::Board::Declare::Meta::Role::Attribute::Container; +use Moose::Role; +Moose::Util::meta_attribute_alias('Container'); + +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', + (Moose->VERSION >= 2.0100 + ? '$type_message' + : '$type_constraint_obj'), + )) . "\n" + . '}' . "\n" + . '$val' . "\n" + . '}'; +}; + +no Moose::Role; + +1; -- cgit v1.2.3-54-g00ecf