Add a remove_keywords function so if you extend Moose you don't have to cargo cult...
Shawn M Moore [Mon, 4 Aug 2008 01:34:26 +0000 (01:34 +0000)]
Changes
lib/Moose.pm
lib/Moose/Cookbook/Extending/Recipe2.pod

diff --git a/Changes b/Changes
index afb63a4..175298b 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,11 @@
 Revision history for Perl extension Moose
 
+0.56
+    * Moose
+    * Moose::Cookbook::Extending::Recipe2
+      - Add a remove_keywords function so if you extend Moose
+        you don't have to cargo cult Moose's unimport (Sartak)
+
 0.55 Sun August 3, 2008
     * Moose::Meta::Attribute
       - breaking down the way 'handles' methods are
index 5fba49e..9551c07 100644 (file)
@@ -190,26 +190,40 @@ use Moose::Util ();
     }
 
     sub unimport {
-        no strict 'refs';
         my $class = _get_caller(@_);
 
-        # loop through the exports ...
-        foreach my $name ( keys %exports ) {
+        remove_keywords(
+            source   => __PACKAGE__,
+            package  => $class,
+            keywords => [ keys %exports ],
+        );
+    }
 
-            # if we find one ...
-            if ( defined &{ $class . '::' . $name } ) {
-                my $keyword = \&{ $class . '::' . $name };
+}
 
-                # make sure it is from Moose
-                my ($pkg_name) = Class::MOP::get_code_info($keyword);
-                next if $pkg_name ne 'Moose';
+sub remove_keywords {
+    my ( %args ) = @_;
 
-                # and if it is from Moose then undef the slot
-                delete ${ $class . '::' }{$name};
-            }
+    my $source  = $args{source};
+    my $package = $args{package};
+
+    no strict 'refs';
+
+    # loop through the keywords ...
+    foreach my $name ( @{ $args{keywords} } ) {
+
+        # if we find one ...
+        if ( defined &{ $package . '::' . $name } ) {
+            my $keyword = \&{ $package . '::' . $name };
+
+            # make sure it is from us
+            my ($pkg_name) = Class::MOP::get_code_info($keyword);
+            next if $pkg_name ne $source;
+
+            # and if it is from us, then undef the slot
+            delete ${ $package . '::' }{$name};
         }
     }
-
 }
 
 sub init_meta {
@@ -818,6 +832,19 @@ and optionally a baseclass and a metaclass as arguments.
 
 For more detail on this topic, see L<Moose::Cookbook::Extending::Recipe2>.
 
+=head2 B<remove_keywords>
+
+The remove_keywords method is called by Moose's C<unimport> to remove Moose's
+keywords from a package when C<no Moose> is used. If you extend Moose with
+new keywords, you should provide an C<unimport> that calls C<remove_keywords>
+to remove your sugar.
+
+C<remove_keywords> takes named parameters C<source> (to make sure that we
+don't remove keywords defined by somebody else), C<package> (from which we're
+removing keywords), and C<keywords> (an array reference of keyword names).
+
+For more detail on this topic, see L<Moose::Cookbook::Extending::Recipe2>.
+
 =head1 CAVEATS
 
 =over 4
index 80dbfff..e565e45 100644 (file)
@@ -36,18 +36,11 @@ Moose::Cookbook::Extending::Recipe2 - Acting like Moose.pm and providing sugar M
   sub unimport {
       my $caller = caller();
 
-      no strict 'refs';
-      foreach my $name (@EXPORT) {
-          if ( defined &{ $caller . '::' . $name } ) {
-              my $keyword = \&{ $caller . '::' . $name };
-
-              my ($pkg_name) = Class::MOP::get_code_info($keyword);
-
-              next if $pkg_name ne __PACKAGE__;
-
-              delete ${ $caller . '::' }{$name};
-          }
-      }
+      Moose::remove_keywords(
+          source   => __PACKAGE__,
+          package  => $caller,
+          keywords => \@EXPORT,
+      );
 
       Moose::unimport( { into_level => 1 } );
   }
@@ -129,9 +122,11 @@ This is all a bit fragile since it doesn't stack terribly well. You
 can basically only have one Moose-alike module. This may be fixed in
 the still-notional C<MooseX::Exporter> module someday.
 
-The C<unimport()> subroutine is basically a copy of the C<unimport()>
-from C<Moose.pm>. You can copy this verbatim into your code. Again,
-this doesn't stack well.
+The C<unimport()> subroutine calls the C<remove_keywords> function
+from Moose.  This function removes only the keywords exported by
+this module. More precisely, C<remove_keywords> removes from the
+C<package> package the keywords given by the C<keywords> argument
+that were created in the C<source> package.
 
 Finally, we have our C<has_table()> subroutine. This provides a bit of
 sugar that looks a lot like C<has()>.