summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/MooseX/Bread/Board/Meta/Role/Accessor.pm26
-rw-r--r--lib/MooseX/Bread/Board/Meta/Role/Attribute.pm31
-rw-r--r--t/04-block.t2
-rw-r--r--t/30-type-checks.t26
-rw-r--r--t/31-auto-deref.t44
5 files changed, 122 insertions, 7 deletions
diff --git a/lib/MooseX/Bread/Board/Meta/Role/Accessor.pm b/lib/MooseX/Bread/Board/Meta/Role/Accessor.pm
new file mode 100644
index 0000000..10748e0
--- /dev/null
+++ b/lib/MooseX/Bread/Board/Meta/Role/Accessor.pm
@@ -0,0 +1,26 @@
+package MooseX::Bread::Board::Meta::Role::Accessor;
+use Moose::Role;
+
+around _inline_get => sub {
+ my $orig = shift;
+ my $self = shift;
+ my ($instance) = @_;
+
+ my $attr = $self->associated_attribute;
+
+ return 'do {' . "\n"
+ . 'my $val;' . "\n"
+ . 'if (' . $self->_inline_has($instance) . ') {' . "\n"
+ . '$val = ' . $self->$orig($instance) . ';' . "\n"
+ . '}' . "\n"
+ . 'else {' . "\n"
+ . '$val = ' . $instance . '->get_service(\'' . $attr->name . '\')->get;' . "\n"
+ . $self->_inline_check_constraint('$val')
+ . '}' . "\n"
+ . '$val' . "\n"
+ . '}';
+};
+
+no Moose::Role;
+
+1;
diff --git a/lib/MooseX/Bread/Board/Meta/Role/Attribute.pm b/lib/MooseX/Bread/Board/Meta/Role/Attribute.pm
index fe98bb7..9f4c16e 100644
--- a/lib/MooseX/Bread/Board/Meta/Role/Attribute.pm
+++ b/lib/MooseX/Bread/Board/Meta/Role/Attribute.pm
@@ -91,17 +91,36 @@ around get_value => sub {
return $self->$orig($instance)
if $self->has_value($instance);
- return $instance->get_service($self->name)->get;
+ my $val = $instance->get_service($self->name)->get;
+
+ $self->verify_against_type_constraint($val, instance => $instance)
+ if $self->has_type_constraint;
+
+ if ($self->should_auto_deref) {
+ if (ref($val) eq 'ARRAY') {
+ return wantarray ? @$val : $val;
+ }
+ elsif (ref($val) eq 'HASH') {
+ return wantarray ? %$val : $val;
+ }
+ else {
+ die 'XXX';
+ }
+ }
+ else {
+ return $val;
+ }
};
-around inline_get => sub {
+around accessor_metaclass => sub {
my $orig = shift;
my $self = shift;
- my ($instance) = @_;
- return 'do { (' . $self->inline_has($instance) . ')' . "\n"
- . '? (' . $self->$orig($instance) . ')' . "\n"
- . ': (' . $instance . '->get_service(\'' . $self->name . '\')->get) }';
+ return Moose::Meta::Class->create_anon_class(
+ superclasses => [ $self->$orig(@_) ],
+ roles => [ 'MooseX::Bread::Board::Meta::Role::Accessor' ],
+ cache => 1
+ )->name;
};
no Moose::Role;
diff --git a/t/04-block.t b/t/04-block.t
index a06a950..c0f9bad 100644
--- a/t/04-block.t
+++ b/t/04-block.t
@@ -22,7 +22,7 @@ use Test::More;
has baz => (
is => 'ro',
- isa => 'Baz',
+ isa => 'Str',
block => sub {
my ($s, $self) = @_;
return $s->param('bar') . $self->foo;
diff --git a/t/30-type-checks.t b/t/30-type-checks.t
new file mode 100644
index 0000000..58f4405
--- /dev/null
+++ b/t/30-type-checks.t
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+use Test::Fatal;
+
+{
+ package Foo;
+ use Moose;
+ use MooseX::Bread::Board;
+
+ has foo => (
+ is => 'ro',
+ isa => 'Ref',
+ value => 'FOO',
+ );
+}
+
+{
+ my $foo = Foo->new;
+ like(exception { $foo->foo },
+ qr/^Attribute \(foo\) does not pass the type constraint because: Validation failed for 'Ref' with value FOO/,
+ "error when service returns invalid value");
+}
+
+done_testing;
diff --git a/t/31-auto-deref.t b/t/31-auto-deref.t
new file mode 100644
index 0000000..c86fffd
--- /dev/null
+++ b/t/31-auto-deref.t
@@ -0,0 +1,44 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+
+{
+ package Foo;
+ use Moose;
+ use MooseX::Bread::Board;
+
+ has foo => (
+ is => 'ro',
+ isa => 'ArrayRef',
+ auto_deref => 1,
+ block => sub { ['foo', 'bar'] },
+ );
+
+ has bar => (
+ is => 'ro',
+ isa => 'HashRef',
+ auto_deref => 1,
+ block => sub { {'foo' => 'bar'} },
+ );
+}
+
+{
+ my $foo = Foo->new;
+
+ is_deeply(scalar($foo->foo), ['foo', 'bar'], "scalar array");
+ is_deeply([$foo->foo], ['foo', 'bar'], "list array");
+ is_deeply(scalar($foo->bar), {'foo', 'bar'}, "scalar hash");
+ is_deeply({$foo->foo}, {'foo', 'bar'}, "list hash");
+}
+
+{
+ my $foo = Foo->new(foo => ['foo', 'bar'], bar => {'foo' => 'bar'});
+
+ is_deeply(scalar($foo->foo), ['foo', 'bar'], "scalar array");
+ is_deeply([$foo->foo], ['foo', 'bar'], "list array");
+ is_deeply(scalar($foo->bar), {'foo', 'bar'}, "scalar hash");
+ is_deeply({$foo->foo}, {'foo', 'bar'}, "list hash");
+}
+
+done_testing;