Rename Meta::Recipe3 to Meta::Labeled_AttributeTrait
[gitmo/Moose.git] / lib / Moose / Cookbook / Extending / Recipe1.pod
index 4449ebd..c4d41c6 100644 (file)
@@ -1,9 +1,11 @@
+package Moose::Cookbook::Extending::Recipe1;
 
-=pod
+# ABSTRACT: Moose extension overview
+
+__END__
 
-=head1 NAME
 
-Moose::Cookbook::Extending::Recipe1 - Moose extension overview
+=pod
 
 =head1 DESCRIPTION
 
@@ -37,20 +39,19 @@ a few broad categories.
 =head2 Metaclass Extensions
 
 One way of extending Moose is by extending one or more Moose
-metaclasses. For example, in L<Moose::Cookbook::Meta::Recipe4> we saw
-a metaclass subclass that added a C<table> attribute to the
+metaclasses. For example, in L<Moose::Cookbook::Meta::Recipe5> we saw
+a metaclass role that added a C<table> attribute to the
 metaclass. If you were writing an ORM, this would be a logical
 extension.
 
 Many of the Moose extensions on CPAN work by providing an attribute
-metaclass extension. For example, the L<MooseX::AttributeHelpers>
-distribution provides a new attribute metaclass that lets you delegate
-behavior to a non-object attribute (a hashref or simple number).
+metaclass role. For example, the L<MooseX::Aliases> module
+provides an attribute metaclass trait that lets you specify aliases
+to install for methods and attribute accessors.
 
-A metaclass extension can be packaged as a subclass or a
-role/trait. If you can, we recommend using traits instead of
-subclasses, since it's much easier to combine disparate traits then it
-is to combine a bunch of subclasses.
+A metaclass extension can be packaged as a role/trait or a subclass. If you
+can, we recommend using traits instead of subclasses, since it's much easier
+to combine disparate traits than it is to combine a bunch of subclasses.
 
 When your extensions are implemented as roles, you can apply them with
 the L<Moose::Util::MetaRole> module.
@@ -65,15 +66,15 @@ recipes.
 
 =head2 Object Class Extensions
 
-Another common Moose extension technique is to change the default
-object class's behavior. For example, the L<MooseX::Singleton>
-extension changes the behavior of your objects so that they are
-singletons. The L<MooseX::StrictConstructor> extension makes the
-constructor reject arguments which don't match its attributes.
+Another common Moose extension technique is to change the default object
+class's behavior. As with metaclass extensions, this can be done with a
+role/trait or with a subclass. For example, L<MooseX::StrictConstructor>
+extension applies a trait that makes the constructor reject arguments which
+don't match its attributes.
 
 Object class extensions often include metaclass extensions as well. In
 particular, if you want your object extension to work when a class is
-made immutable, you may need to extend some or all of the
+made immutable, you may need to modify the behavior of some or all of the
 L<Moose::Meta::Instance>, L<Moose::Meta::Method::Constructor>, and
 L<Moose::Meta::Method::Destructor> objects.
 
@@ -96,7 +97,9 @@ be used via the normal C<with> sugar:
 
    use Moose;
 
-   with 'MooseX::My::Role';
+   with 'My::Role';
+
+Don't use "MooseX" in the name for such packages.
 
 =head2 New Types
 
@@ -109,15 +112,14 @@ this works. These both build on top of the L<MooseX::Types> extension.
 
 =head1 ROLES VS TRAITS VS SUBCLASSES
 
-It is important to understand that B<roles and traits are the same
-thing>. A role can be used as a trait, and a trait is a role. The only
-thing that distinguishes the two is that a trait is packaged in a way
-that lets Moose resolve a short name to a class name. In other words,
-with a trait, the caller can refer to it by a short name like "Big",
-and Moose will resolve it to a class like
-C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
+It is important to understand that B<roles and traits are the same thing>. A
+trait is simply a role applied to a instance. The only thing that may
+distinguish the two is that a trait can be packaged in a way that lets Moose
+resolve a short name to a class name. In other words, with a trait, the caller
+can refer to it by a short name like "Big", and Moose will resolve it to a
+class like C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
 
-See L<Moose::Cookbook::Meta::Recipe3> and
+See L<Moose::Cookbook::Meta::Labeled_AttributeTrait> and
 L<Moose::Cookbook::Meta::Recipe5> for examples of traits in action. In
 particular, both of these recipes demonstrate the trait resolution
 mechanism.
@@ -154,48 +156,6 @@ over what the trait applies to. This is especially true for attribute
 traits, where you can apply the trait to just one attribute in a
 class.
 
-=head2 Extensions as Metaclass (and Base Object) Subclasses
-
-Moose does not provide any simple APIs for consumers to use a subclass
-extension, except for attribute metaclasses. The attribute declaration
-parameters include a C<metaclass> parameter a consumer of your
-extension can use to specify your subclass.
-
-This is one reason why implementing an extension as a subclass can be
-a poor choice. However, you can force the use of certain subclasses at
-import time by calling C<< Moose->init_meta >> for the caller, and
-providing an alternate metaclass or base object class.
-
-If you do want to do this, you should look at using L<Moose::Exporter>
-to re-export the L<Moose.pm|Moose> sugar function. With
-L<Moose::Exporter>, if your exporting class has an C<init_meta>
-method, L<Moose::Exporter> makes sure that this C<init_meta> method
-gets called when your class is imported.
-
-Then in your C<init_meta> you can arrange for the caller to use your
-subclasses:
-
-  package MooseX::Embiggen;
-
-  use Moose ();
-  use Moose::Exporter;
-
-  use MooseX::Embiggen::Meta::Class;
-  use MooseX::Embiggen::Object;
-
-  Moose::Exporter->setup_import_methods( also => 'Moose' );
-
-  sub init_meta {
-      shift;    # just your package name
-      my %options = @_;
-
-      return Moose->init_meta(
-          for_class  => $options{for_class},
-          metaclass  => 'MooseX::Embiggen::Meta::Class',
-          base_class => 'MooseX::Embiggen::Object',
-      );
-  }
-
 =head2 Extensions as Metaclass (and Base Object) Roles
 
 Implementing your extensions as metaclass roles makes your extensions
@@ -209,43 +169,31 @@ L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
 using this module is that I<it preserves any subclassing or roles
 already applied to the user's metaclasses>. This means that your
 extension is cooperative I<by default>, and consumers of your
-extension can easily use it with other role-based extensions.
+extension can easily use it with other role-based extensions. Most
+uses of L<Moose::Util::MetaRole> can be handled by L<Moose::Exporter>
+directly; see the L<Moose::Exporter> docs.
 
   package MooseX::Embiggen;
 
-  use Moose ();
+  use strict;
+  use warnings;
+
   use Moose::Exporter;
-  use Moose::Util::MetaRole;
 
   use MooseX::Embiggen::Role::Meta::Class;
   use MooseX::Embiggen::Role::Meta::Attribute;
   use MooseX::Embiggen::Role::Meta::Method::Constructor;
   use MooseX::Embiggen::Role::Object;
 
-  Moose::Exporter->setup_import_methods( also => 'Moose' );
-
-  sub init_meta {
-      shift;    # just your package name
-      my %options = @_;
-
-      Moose->init_meta(%options);
-
-      my $meta = Moose::Util::MetaRole::apply_metaclass_roles(
-          for_class       => $options{for_class},
-          metaclass_roles => ['MooseX::Embiggen::Role::Meta::Class'],
-          attribute_metaclass_roles =>
-              ['MooseX::Embiggen::Role::Meta::Attribute'],
-          constructor_class_roles =>
+  Moose::Exporter->setup_import_methods(
+      class_metaroles => {
+          class     => ['MooseX::Embiggen::Role::Meta::Class'],
+          attribute => ['MooseX::Embiggen::Role::Meta::Attribute'],
+          constructor =>
               ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
-      );
-
-      Moose::Util::MetaRole::apply_base_class_roles(
-          for_class => $options{for_class},
-          roles     => ['MooseX::Embiggen::Role::Object'],
-      );
-
-      return $meta;
-  }
+      },
+      base_class_roles => ['MooseX::Embiggen::Role::Object'],
+  );
 
 As you can see from this example, you can use L<Moose::Util::MetaRole>
 to apply roles to any metaclass, as well as the base object class. If
@@ -254,24 +202,25 @@ preserved when your extension applies its roles, and vice versa.
 
 =head2 Providing Sugar
 
-With L<Moose::Exporter>, you can also export your own sugar functions,
-as well as those from other modules:
+With L<Moose::Exporter>, you can also export your own sugar functions:
 
   package MooseX::Embiggen;
 
-  use Moose ();
+  use strict;
+  use warnings;
+
   use Moose::Exporter;
 
   Moose::Exporter->setup_import_methods(
-      with_caller => ['embiggen'],
-      also        => 'Moose',
+      with_meta       => ['embiggen'],
+      class_metaroles => {
+          class => ['MooseX::Embiggen::Role::Meta::Class'],
+      },
   );
 
-  sub init_meta { ... }
-
   sub embiggen {
-      my $caller = shift;
-      $caller->meta()->embiggen(@_);
+      my $meta = shift;
+      $meta->embiggen(@_);
   }
 
 And then the consumer of your extension can use your C<embiggen> sub:
@@ -286,6 +235,54 @@ And then the consumer of your extension can use your C<embiggen> sub:
 
 This can be combined with metaclass and base class roles quite easily.
 
+=head2 Extensions as Metaclass (and Base Object) Subclasses
+
+B<Note: We strongly recommend that you provide your extension as a set of
+roles whenever possible>.
+
+Moose does not provide any simple APIs for consumers to use a subclass
+extension, except for attribute metaclasses. The attribute declaration
+options include a C<metaclass> option a consumer of your extension can
+use to specify your subclass.
+
+This is one reason why implementing an extension as a subclass can be
+a poor choice. However, you can force the use of certain subclasses at
+import time by calling C<< Moose->init_meta >> for the caller, and
+providing an alternate metaclass or base object class.
+
+If you do want to do this, you should look at using L<Moose::Exporter>
+to re-export the L<Moose.pm|Moose> sugar function. With
+L<Moose::Exporter>, if your exporting class has an C<init_meta>
+method, L<Moose::Exporter> makes sure that this C<init_meta> method
+gets called when your class is imported.
+
+Then in your C<init_meta> you can arrange for the caller to use your
+subclasses:
+
+  package MooseX::Embiggen;
+
+  use Moose ();
+  use Moose::Exporter;
+
+  use MooseX::Embiggen::Meta::Class;
+  use MooseX::Embiggen::Object;
+
+  Moose::Exporter->setup_import_methods( also => 'Moose' );
+
+  sub init_meta {
+      shift;    # just your package name
+      my %options = @_;
+
+      return Moose->init_meta(
+          for_class  => $options{for_class},
+          metaclass  => 'MooseX::Embiggen::Meta::Class',
+          base_class => 'MooseX::Embiggen::Object',
+      );
+  }
+
+NOTE: Make sure that your C<init_meta> returns the metaclass object, just as
+C<< Moose->init_meta >> does.
+
 =head1 LEGACY EXTENSION MECHANISMS
 
 Before the existence of L<Moose::Exporter> and
@@ -308,17 +305,4 @@ If you can write your extension as one or more metaclass and base
 object roles, please consider doing so. Make sure to read the docs for
 L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
 
-=head1 AUTHOR
-
-Dave Rolsky E<lt>autarch@urth.orgE<gt>
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright 2009 by Infinity Interactive, Inc.
-
-L<http://www.iinteractive.com>
-
-This library is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
-
 =cut