add stubs for BUILD and DEMOLISH to Moose::Object
Jesse Luehrs [Thu, 21 Jan 2010 08:59:30 +0000 (02:59 -0600)]
Changes
lib/Moose/Object.pm
t/030_roles/019_build.t

diff --git a/Changes b/Changes
index 20bd23c..3f363b4 100644 (file)
--- a/Changes
+++ b/Changes
@@ -5,6 +5,8 @@ for, noteworthy changes.
 
   * Moose::Object::does no longer checks the entire inheritance tree, since
     Moose::Meta::Class::does_role already does this. (doy)
+  * Moose::Object now has stubs for BUILD and DEMOLISH, so they can be safely
+    wrapped in roles without needing to provide your own stubs. (doy)
 
 0.94 Mon, Jan 18, 2010
 
index 1cd1f6a..6aee996 100644 (file)
@@ -48,13 +48,16 @@ sub BUILDALL {
     # NOTE: we ask Perl if we even
     # need to do this first, to avoid
     # extra meta level calls
-    return unless $_[0]->can('BUILD');
+    return if $_[0]->can('BUILD') == \&BUILD;
     my ($self, $params) = @_;
     foreach my $method (reverse Class::MOP::class_of($self)->find_all_methods_by_name('BUILD')) {
+        next if $method->{class} eq __PACKAGE__;
         $method->{code}->execute($self, $params);
     }
 }
 
+sub BUILD { }
+
 sub DEMOLISHALL {
     my $self = shift;
     my ($in_global_destruction) = @_;
@@ -62,7 +65,7 @@ sub DEMOLISHALL {
     # NOTE: we ask Perl if we even
     # need to do this first, to avoid
     # extra meta level calls
-    return unless $self->can('DEMOLISH');
+    return if $self->can('DEMOLISH') == \&DEMOLISH;
 
     my @isa;
     if ( my $meta = Class::MOP::class_of($self ) ) {
@@ -78,12 +81,15 @@ sub DEMOLISHALL {
 
     foreach my $class (@isa) {
         no strict 'refs';
+        next if $class eq __PACKAGE__;
         my $demolish = *{"${class}::DEMOLISH"}{CODE};
         $self->$demolish($in_global_destruction)
             if defined $demolish;
     }
 }
 
+sub DEMOLISH { }
+
 sub DESTROY {
     my $self = shift;
 
index 1dfc912..41fb2cf 100644 (file)
@@ -2,6 +2,7 @@
 use strict;
 use warnings;
 use Test::More;
+use Test::Moose;
 BEGIN {
     eval "use Test::Output;";
     plan skip_all => "Test::Output is required for this test" if $@;
@@ -11,6 +12,8 @@ BEGIN {
 # role: sub BUILD, after BUILD
 # continues to work to run code after object initialization, whether the class
 # has a BUILD method or not
+# note: as of moose 0.95, this idiom is no longer necessary ('after BUILD' on
+# its own is sufficient)  -doy
 
 my @CALLS;
 
@@ -51,7 +54,35 @@ do {
     with 'TestRole';
 };
 
-{
+do {
+    package TestRoleWithoutBUILD;
+    use Moose::Role;
+
+    before BUILD => sub { push @CALLS, 'TestRoleWithoutBUILD::BUILD:before' };
+    after  BUILD => sub { push @CALLS, 'TestRoleWithoutBUILD::BUILD:after' };
+};
+
+do {
+    package AnotherClassWithBUILD;
+    use Moose;
+
+    ::stderr_is {
+        with 'TestRoleWithoutBUILD';
+    } '';
+
+    sub BUILD { push @CALLS, 'AnotherClassWithBUILD::BUILD' }
+};
+
+do {
+    package AnotherClassWithoutBUILD;
+    use Moose;
+
+    ::stderr_is {
+        with 'TestRoleWithoutBUILD';
+    } '';
+};
+
+with_immutable {
     is_deeply([splice @CALLS], [], "no calls to BUILD yet");
 
     ClassWithBUILD->new;
@@ -70,11 +101,21 @@ do {
         'TestRole::BUILD:after',
     ]);
 
-    if (ClassWithBUILD->meta->is_mutable) {
-        ClassWithBUILD->meta->make_immutable;
-        ClassWithoutBUILD->meta->make_immutable;
-        redo;
-    }
-}
+    AnotherClassWithBUILD->new;
+
+    is_deeply([splice @CALLS], [
+        'TestRoleWithoutBUILD::BUILD:before',
+        'AnotherClassWithBUILD::BUILD',
+        'TestRoleWithoutBUILD::BUILD:after',
+    ]);
+
+    AnotherClassWithoutBUILD->new;
+
+    is_deeply([splice @CALLS], [
+        'TestRoleWithoutBUILD::BUILD:before',
+        'TestRoleWithoutBUILD::BUILD:after',
+    ]);
+} qw(ClassWithBUILD        ClassWithoutBUILD
+     AnotherClassWithBUILD AnotherClassWithoutBUILD);
 
 done_testing;