Implementation of auto_deref
Shawn M Moore [Tue, 10 Jun 2008 05:26:11 +0000 (05:26 +0000)]
lib/Mouse/Meta/Attribute.pm
t/026-auto-deref.t

index 2e626b0..64d3d6e 100644 (file)
@@ -17,20 +17,21 @@ sub new {
     bless \%args, $class;
 }
 
-sub name            { $_[0]->{name}            }
-sub class           { $_[0]->{class}           }
-sub _is_metadata    { $_[0]->{is}              }
-sub is_required     { $_[0]->{required}        }
-sub default         { $_[0]->{default}         }
-sub is_lazy         { $_[0]->{lazy}            }
-sub predicate       { $_[0]->{predicate}       }
-sub clearer         { $_[0]->{clearer}         }
-sub handles         { $_[0]->{handles}         }
-sub is_weak_ref     { $_[0]->{weak_ref}        }
-sub init_arg        { $_[0]->{init_arg}        }
-sub type_constraint { $_[0]->{type_constraint} }
-sub trigger         { $_[0]->{trigger}         }
-sub builder         { $_[0]->{builder}         }
+sub name              { $_[0]->{name}            }
+sub class             { $_[0]->{class}           }
+sub _is_metadata      { $_[0]->{is}              }
+sub is_required       { $_[0]->{required}        }
+sub default           { $_[0]->{default}         }
+sub is_lazy           { $_[0]->{lazy}            }
+sub predicate         { $_[0]->{predicate}       }
+sub clearer           { $_[0]->{clearer}         }
+sub handles           { $_[0]->{handles}         }
+sub is_weak_ref       { $_[0]->{weak_ref}        }
+sub init_arg          { $_[0]->{init_arg}        }
+sub type_constraint   { $_[0]->{type_constraint} }
+sub trigger           { $_[0]->{trigger}         }
+sub builder           { $_[0]->{builder}         }
+sub should_auto_deref { $_[0]->{auto_deref}      }
 
 sub has_default         { exists $_[0]->{default}         }
 sub has_predicate       { exists $_[0]->{predicate}       }
@@ -93,7 +94,20 @@ sub generate_accessor {
         $accessor .= ' if !exists($self->{$key});';
     }
 
-    $accessor .= 'return $self->{$key}
+    if ($attribute->should_auto_deref) {
+        if ($attribute->type_constraint eq 'ArrayRef') {
+            $accessor .= 'if (wantarray) {
+                return @{ $self->{$key} || [] };
+            }';
+        }
+        else {
+            $accessor .= 'if (wantarray) {
+                return %{ $self->{$key} || {} };
+            }';
+        }
+    }
+
+    $accessor .= 'return $self->{$key};
     }';
 
     return eval $accessor;
index 0aa021e..0edffed 100644 (file)
@@ -40,20 +40,14 @@ lives_ok {
 is($obj->array, undef, "array without value is undef in scalar context");
 is($obj->hash, undef, "hash without value is undef in scalar context");
 
-TODO: {
-    local $TODO = "auto_deref not implemented";
-    is(@array, 0, "array without value is empty in list context");
-    is(keys %hash, 0, "hash without value is empty in list context");
-};
+is(@array, 0, "array without value is empty in list context");
+is(keys %hash, 0, "hash without value is empty in list context");
 
 @array = $obj->array([1, 2, 3]);
 %hash  = $obj->hash({foo => 1, bar => 2});
 
-TODO: {
-    local $TODO = "auto_deref not implemented";
-    is_deeply(\@array, [1, 2, 3], "setter returns the dereferenced list");
-    is_deeply(\%hash, {foo => 1, bar => 2}, "setter returns the dereferenced hash");
-};
+is_deeply(\@array, [1, 2, 3], "setter returns the dereferenced list");
+is_deeply(\%hash, {foo => 1, bar => 2}, "setter returns the dereferenced hash");
 
 lives_ok {
     @array = $obj->array;
@@ -68,9 +62,6 @@ lives_ok {
 is_deeply($array, [1, 2, 3], "auto_deref in scalar context gives the reference");
 is_deeply($hash, {foo => 1, bar => 2}, "auto_deref in scalar context gives the reference");
 
-TODO: {
-    local $TODO = "auto_deref not implemented";
-    is_deeply(\@array, [1, 2, 3], "auto_deref in list context gives the list");
-    is_deeply(\%hash, {foo => 1, bar => 2}, "auto_deref in list context gives the hash");
-};
+is_deeply(\@array, [1, 2, 3], "auto_deref in list context gives the list");
+is_deeply(\%hash, {foo => 1, bar => 2}, "auto_deref in list context gives the hash");