Fix type coersion of lazy values accessed using the get_value method. I've RFC'd...
Tomas Doran [Wed, 20 Aug 2008 14:02:18 +0000 (14:02 +0000)]
Changes
lib/Moose/Meta/Attribute.pm
t/040_type_constraints/025_type_coersion_on_lazy_attributes.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index fc59bac..041a1e6 100644 (file)
--- a/Changes
+++ b/Changes
@@ -5,6 +5,10 @@ Revision history for Perl extension Moose
       - Fix inlined constructor so that values produced by default
         or builder methods are coerced as required + test (t0m)
 
+    * Moose::Meta::Attribute
+      - Fix lazy built attributes so that type coersion always
+        occurs on them when accessed with get_value method + test (t0m)
+
     * Moose::Exporter
       - This is a new helper module for writing "Moose-alike"
         modules. This should make the lives of MooseX module authors
index 2334770..69e6006 100644 (file)
@@ -8,7 +8,7 @@ use Scalar::Util 'blessed', 'weaken';
 use Carp         'confess';
 use overload     ();
 
-our $VERSION   = '0.56';
+our $VERSION   = '0.57';
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Moose::Meta::Method::Accessor;
@@ -489,12 +489,12 @@ sub get_value {
 
     if ($self->is_lazy) {
         unless ($self->has_value($instance)) {
+            my $value;
             if ($self->has_default) {
-                my $default = $self->default($instance);
-                $self->set_initial_value($instance, $default);
+                $value = $self->default($instance);
             } elsif ( $self->has_builder ) {
                 if (my $builder = $instance->can($self->builder)){
-                    $self->set_initial_value($instance, $instance->$builder);
+                    $value = $instance->$builder;
                 }
                 else {
                     confess(blessed($instance) 
@@ -505,9 +505,16 @@ sub get_value {
                           . "'");
                 }
             } 
-            else {
-                $self->set_initial_value($instance, undef);
+            if ($self->has_type_constraint) {
+                my $type_constraint = $self->type_constraint;
+                $value = $type_constraint->coerce($value)
+                    if ($self->should_coerce);
+                $type_constraint->check($value) 
+                  || confess "Attribute (" . $self->name
+                      . "') does not pass the type constraint because: "
+                      . $type_constraint->get_message($value);
             }
+            $self->set_initial_value($instance, $value);
         }
     }
 
diff --git a/t/040_type_constraints/025_type_coersion_on_lazy_attributes.t b/t/040_type_constraints/025_type_coersion_on_lazy_attributes.t
new file mode 100644 (file)
index 0000000..5f11fb6
--- /dev/null
@@ -0,0 +1,23 @@
+{
+    package SomeClass;
+    use Moose;
+    use Moose::Util::TypeConstraints;
+
+    subtype 'DigitSix' => as 'Num'
+        => where { /^6$/ };
+    subtype 'TextSix' => as 'Str'
+        => where { /Six/i };
+    coerce 'TextSix' 
+        => from 'DigitSix' 
+        => via { confess("Cannot live without 6 ($_)") unless /^6$/; 'Six' };
+
+    has foo => ( isa => 'TextSix', coerce => 1, is => 'ro', default => 6,
+        lazy => 1
+    ); 
+}
+
+use Test::More tests => 2;
+my $attr = SomeClass->meta->get_attribute('foo');
+is($attr->get_value(SomeClass->new()), 'Six');
+is(SomeClass->new()->foo, 'Six');
+