Moose::Cookbook::Extending::Recipe1 man page on Fedora

Man page or keyword search:  
man Server   31170 pages
apropos Keyword Search (all sections)
Output format
Fedora logo
[printable version]

Moose::Cookbook::ExtenUser:Contributed PMoose::Cookbook::Extending::Recipe1(3)

NAME
       Moose::Cookbook::Extending::Recipe1 - Moose extension overview

VERSION
       version 2.0402

DESCRIPTION
       Moose provides several ways in which extensions can hook into Moose and
       change its behavior. Moose also has a lot of behavior that can be
       changed. This recipe will provide an overview of each extension method
       and give you some recommendations on what tools to use.

       If you haven't yet read the recipes on metaclasses, go read those
       first. You can't write Moose extensions without understanding the
       metaclasses, and those recipes also demonstrate some basic extension
       mechanisms, such as metaclass subclasses and traits.

   Playing Nice With Others
       One of the goals of this overview is to help you build extensions that
       cooperate well with other extensions. This is especially important if
       you plan to release your extension to CPAN.

       Moose comes with several modules that exist to help your write
       cooperative extensions. These are Moose::Exporter and
       Moose::Util::MetaRole. By using these two modules, you will ensure that
       your extension works with both the Moose core features and any other
       CPAN extension using those modules.

PARTS OF Moose YOU CAN EXTEND
       The types of things you might want to do in Moose extensions fall into
       a few broad categories.

   Metaclass Extensions
       One way of extending Moose is by extending one or more Moose
       metaclasses. For example, in Moose::Cookbook::Meta::Recipe4 we saw a
       metaclass subclass that added a "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 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 than it is to combine a bunch
       of subclasses.

       When your extensions are implemented as roles, you can apply them with
       the Moose::Util::MetaRole module.

   Providing Sugar Functions
       As part of a metaclass extension, you may also want to provide some
       sugar functions, just like Moose.pm does. Moose provides a helper
       module called Moose::Exporter that makes this much simpler. We will be
       use Moose::Exporter in several of the extension recipes.

   Object Class Extensions
       Another common Moose extension technique is to change the default
       object class's behavior. For example, the MooseX::Singleton extension
       changes the behavior of your objects so that they are singletons. The
       MooseX::StrictConstructor extension 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
       Moose::Meta::Instance, Moose::Meta::Method::Constructor, and
       Moose::Meta::Method::Destructor objects.

       The Moose::Util::MetaRole module lets you apply roles to the base
       object class, as well as the meta classes just mentioned.

   Providing a Role
       Some extensions come in the form of a role for you to consume. The
       MooseX::Object::Pluggable extension is a great example of this. In
       fact, despite the "MooseX" name, it does not actually change anything
       about Moose's behavior. Instead, it is just a role that an object which
       wants to be pluggable can consume.

       If you are implementing this sort of extension, you don't need to do
       anything special. You simply create a role and document that it should
       be used via the normal "with" sugar:

	  package MyApp::User;

	  use Moose;

	  with 'MooseX::My::Role';

   New Types
       Another common Moose extension is a new type for the Moose type system.
       In this case, you simply create a type in your module. When people load
       your module, the type is created, and they can refer to it by name
       after that. The MooseX::Types::URI and MooseX::Types::DateTime
       distributions are two good examples of how this works. These both build
       on top of the MooseX::Types extension.

ROLES VS TRAITS VS SUBCLASSES
       It is important to understand that 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
       "MooseX::Embiggen::Meta::Attribute::Role::Big".

       See Moose::Cookbook::Meta::Recipe3 and Moose::Cookbook::Meta::Recipe5
       for examples of traits in action. In particular, both of these recipes
       demonstrate the trait resolution mechanism.

       Implementing an extension as a (set of) metaclass or base object
       role(s) will make your extension more cooperative. It is hard for an
       end-user to effectively combine together multiple metaclass subclasses,
       but it is very easy to combine roles.

USING YOUR EXTENSION
       There are a number of ways in which an extension can be applied. In
       some cases you can provide multiple ways of consuming your extension.

   Extensions as Metaclass Traits
       If your extension is available as a trait, you can ask end users to
       simply specify it in a list of traits. Currently, this only works for
       (class) metaclass and attribute metaclass traits:

	 use Moose -traits => [ 'Big', 'Blue' ];

	 has 'animal' => (
	     traits => [ 'Big', 'Blue' ],
	     ...
	 );

       If your extension applies to any other metaclass, or the object base
       class, you cannot use the trait mechanism.

       The benefit of the trait mechanism is that is very easy to see where a
       trait is applied in the code, and consumers have fine-grained control
       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.

   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
       options include a "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 "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 Moose::Exporter to
       re-export the Moose.pm sugar function. With Moose::Exporter, if your
       exporting class has an "init_meta" method, Moose::Exporter makes sure
       that this "init_meta" method gets called when your class is imported.

       Then in your "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 "init_meta" returns the metaclass object,
       just as "Moose->init_meta" does.

   Extensions as Metaclass (and Base Object) Roles
       Implementing your extensions as metaclass roles makes your extensions
       easy to apply, and cooperative with other role-based extensions for
       metaclasses.

       Just as with a subclass, you will probably want to package your
       extensions for consumption with a single module that uses
       Moose::Exporter. However, in this case, you will use
       Moose::Util::MetaRole to apply all of your roles. The advantage of
       using this module is that it preserves any subclassing or roles already
       applied to the user's metaclasses. This means that your extension is
       cooperative by default, and consumers of your extension can easily use
       it with other role-based extensions. Most uses of Moose::Util::MetaRole
       can be handled by Moose::Exporter directly; see the Moose::Exporter
       docs.

	 package MooseX::Embiggen;

	 use Moose ();
	 use Moose::Exporter;

	 use MooseX::Embiggen::Role::Meta::Class;
	 use MooseX::Embiggen::Role::Meta::Attribute;
	 use MooseX::Embiggen::Role::Meta::Method::Constructor;
	 use MooseX::Embiggen::Role::Object;

	 my ( $import, $unimport, $init_meta ) = Moose::Exporter->build_import_methods(
	     also => ['Moose'], metaclass_roles =>
		 ['MooseX::Embiggen::Role::Meta::Class'],
	     attribute_metaclass_roles => ['MooseX::Embiggen::Role::Meta::Attribute'],
	     constructor_class_roles =>
		 ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
	     base_class_roles => ['MooseX::Embiggen::Role::Object'],
	     install	      => [qw(import unimport)],
	 );

	 sub init_meta {
	     my $package = shift;
	     my %options = @_;
	     Moose->init_meta(%options);
	     return $package->$init_meta(%options);
	 }

       As you can see from this example, you can use Moose::Util::MetaRole to
       apply roles to any metaclass, as well as the base object class. If some
       other extension has already applied its own roles, they will be
       preserved when your extension applies its roles, and vice versa.

   Providing Sugar
       With Moose::Exporter, you can also export your own sugar functions, as
       well as those from other modules:

	 package MooseX::Embiggen;

	 use Moose ();
	 use Moose::Exporter;

	 Moose::Exporter->setup_import_methods(
	     with_meta => ['embiggen'],
	     also      => 'Moose',
	 );

	 sub embiggen {
	     my $meta = shift;
	     $meta->embiggen(@_);
	 }

       And then the consumer of your extension can use your "embiggen" sub:

	 package Consumer;

	 use MooseX::Embiggen;

	 extends 'Thing';

	 embiggen ...;

       This can be combined with metaclass and base class roles quite easily.

LEGACY EXTENSION MECHANISMS
       Before the existence of Moose::Exporter and Moose::Util::MetaRole,
       there were a number of other ways to extend Moose. In general, these
       methods were less cooperative, and only worked well with a single
       extension.

       These methods include metaclass.pm, Moose::Policy (which uses
       metaclass.pm under the hood), and various hacks to do what
       Moose::Exporter does. Please do not use these for your own extensions.

       Note that if you write a cooperative extension, it should cooperate
       with older extensions, though older extensions generally do not
       cooperate with each other.

CONCLUSION
       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
       Moose::Exporter and Moose::Util::MetaRole as well.

AUTHOR
       Moose is maintained by the Moose Cabal, along with the help of many
       contributors. See "CABAL" in Moose and "CONTRIBUTORS" in Moose for
       details.

COPYRIGHT AND LICENSE
       This software is copyright (c) 2012 by Infinity Interactive, Inc..

       This is free software; you can redistribute it and/or modify it under
       the same terms as the Perl 5 programming language system itself.

perl v5.14.2			  2012-0Moose::Cookbook::Extending::Recipe1(3)
[top]

List of man pages available for Fedora

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net