calling Moose->init_meta yourself really shouldn't be recommended
[gitmo/Moose.git] / lib / Moose / Cookbook / Extending / ExtensionOverview.pod
CommitLineData
3b788714 1package Moose::Cookbook::Extending::ExtensionOverview;
c8d5f1e1 2
daa0fd7d 3# ABSTRACT: Moose extension overview
4
5__END__
c8d5f1e1 6
c8d5f1e1 7
daa0fd7d 8=pod
c8d5f1e1 9
10=head1 DESCRIPTION
11
0558aab4 12Moose provides several ways in which extensions can hook into Moose
13and change its behavior. Moose also has a lot of behavior that can be
14changed. This recipe will provide an overview of each extension method
15and give you some recommendations on what tools to use.
c8d5f1e1 16
17If you haven't yet read the recipes on metaclasses, go read those
0558aab4 18first. You can't write Moose extensions without understanding the
19metaclasses, and those recipes also demonstrate some basic extension
20mechanisms, such as metaclass subclasses and traits.
c8d5f1e1 21
22=head2 Playing Nice With Others
23
24One of the goals of this overview is to help you build extensions that
25cooperate well with other extensions. This is especially important if
26you plan to release your extension to CPAN.
27
28Moose comes with several modules that exist to help your write
29cooperative extensions. These are L<Moose::Exporter> and
0558aab4 30L<Moose::Util::MetaRole>. By using these two modules, you will ensure
31that your extension works with both the Moose core features and any
32other CPAN extension using those modules.
c8d5f1e1 33
34=head1 PARTS OF Moose YOU CAN EXTEND
35
0558aab4 36The types of things you might want to do in Moose extensions fall into
37a few broad categories.
c8d5f1e1 38
39=head2 Metaclass Extensions
40
41One way of extending Moose is by extending one or more Moose
826230c2 42metaclasses. For example, in L<Moose::Cookbook::Meta::Table_MetaclassTrait> we saw
546a18e9 43a metaclass role that added a C<table> attribute to the
c8d5f1e1 44metaclass. If you were writing an ORM, this would be a logical
45extension.
46
47Many of the Moose extensions on CPAN work by providing an attribute
546a18e9 48metaclass role. For example, the L<MooseX::Aliases> module
d50f0281 49provides an attribute metaclass trait that lets you specify aliases
50to install for methods and attribute accessors.
c8d5f1e1 51
546a18e9 52A metaclass extension can be packaged as a role/trait or a subclass. If you
53can, we recommend using traits instead of subclasses, since it's much easier
54to combine disparate traits than it is to combine a bunch of subclasses.
c8d5f1e1 55
56When your extensions are implemented as roles, you can apply them with
57the L<Moose::Util::MetaRole> module.
58
0558aab4 59=head2 Providing Sugar Functions
c8d5f1e1 60
61As part of a metaclass extension, you may also want to provide some
0558aab4 62sugar functions, just like L<Moose.pm|Moose> does. Moose provides a
63helper module called L<Moose::Exporter> that makes this much
64simpler. We will be use L<Moose::Exporter> in several of the extension
65recipes.
c8d5f1e1 66
67=head2 Object Class Extensions
68
546a18e9 69Another common Moose extension technique is to change the default object
70class's behavior. As with metaclass extensions, this can be done with a
71role/trait or with a subclass. For example, L<MooseX::StrictConstructor>
72extension applies a trait that makes the constructor reject arguments which
73don't match its attributes.
c8d5f1e1 74
0558aab4 75Object class extensions often include metaclass extensions as well. In
c8d5f1e1 76particular, if you want your object extension to work when a class is
546a18e9 77made immutable, you may need to modify the behavior of some or all of the
0558aab4 78L<Moose::Meta::Instance>, L<Moose::Meta::Method::Constructor>, and
79L<Moose::Meta::Method::Destructor> objects.
c8d5f1e1 80
81The L<Moose::Util::MetaRole> module lets you apply roles to the base
82object class, as well as the meta classes just mentioned.
83
84=head2 Providing a Role
85
86Some extensions come in the form of a role for you to consume. The
0558aab4 87L<MooseX::Object::Pluggable> extension is a great example of this. In
c8d5f1e1 88fact, despite the C<MooseX> name, it does not actually change anything
89about Moose's behavior. Instead, it is just a role that an object
90which wants to be pluggable can consume.
91
92If you are implementing this sort of extension, you don't need to do
93anything special. You simply create a role and document that it should
94be used via the normal C<with> sugar:
95
0558aab4 96 package MyApp::User;
c8d5f1e1 97
98 use Moose;
99
546a18e9 100 with 'My::Role';
101
102Don't use "MooseX" in the name for such packages.
c8d5f1e1 103
104=head2 New Types
105
106Another common Moose extension is a new type for the Moose type
107system. In this case, you simply create a type in your module. When
108people load your module, the type is created, and they can refer to it
0558aab4 109by name after that. The L<MooseX::Types::URI> and
110L<MooseX::Types::DateTime> distributions are two good examples of how
111this works. These both build on top of the L<MooseX::Types> extension.
c8d5f1e1 112
113=head1 ROLES VS TRAITS VS SUBCLASSES
114
713eb831 115It is important to understand that B<roles and traits are the same thing>. A
9bc4e3da 116trait is simply a role applied to a instance. The only thing that may
713eb831 117distinguish the two is that a trait can be packaged in a way that lets Moose
118resolve a short name to a class name. In other words, with a trait, the caller
119can refer to it by a short name like "Big", and Moose will resolve it to a
120class like C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
c8d5f1e1 121
b1301316 122See L<Moose::Cookbook::Meta::Labeled_AttributeTrait> and
826230c2 123L<Moose::Cookbook::Meta::Table_MetaclassTrait> for examples of traits in
124action. In particular, both of these recipes demonstrate the trait resolution
c8d5f1e1 125mechanism.
126
127Implementing an extension as a (set of) metaclass or base object
128role(s) will make your extension more cooperative. It is hard for an
129end-user to effectively combine together multiple metaclass
0558aab4 130subclasses, but it is very easy to combine roles.
c8d5f1e1 131
132=head1 USING YOUR EXTENSION
133
134There are a number of ways in which an extension can be applied. In
135some cases you can provide multiple ways of consuming your extension.
136
137=head2 Extensions as Metaclass Traits
138
139If your extension is available as a trait, you can ask end users to
140simply specify it in a list of traits. Currently, this only works for
0558aab4 141(class) metaclass and attribute metaclass traits:
c8d5f1e1 142
143 use Moose -traits => [ 'Big', 'Blue' ];
144
6a7e3999 145 has 'animal' => (
146 traits => [ 'Big', 'Blue' ],
147 ...
148 );
c8d5f1e1 149
150If your extension applies to any other metaclass, or the object base
151class, you cannot use the trait mechanism.
152
153The benefit of the trait mechanism is that is very easy to see where a
154trait is applied in the code, and consumers have fine-grained control
155over what the trait applies to. This is especially true for attribute
156traits, where you can apply the trait to just one attribute in a
157class.
158
c8d5f1e1 159=head2 Extensions as Metaclass (and Base Object) Roles
160
161Implementing your extensions as metaclass roles makes your extensions
0558aab4 162easy to apply, and cooperative with other role-based extensions for
163metaclasses.
c8d5f1e1 164
165Just as with a subclass, you will probably want to package your
166extensions for consumption with a single module that uses
167L<Moose::Exporter>. However, in this case, you will use
168L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
169using this module is that I<it preserves any subclassing or roles
0558aab4 170already applied to the user's metaclasses>. This means that your
c8d5f1e1 171extension is cooperative I<by default>, and consumers of your
95056a1e 172extension can easily use it with other role-based extensions. Most
173uses of L<Moose::Util::MetaRole> can be handled by L<Moose::Exporter>
174directly; see the L<Moose::Exporter> docs.
c8d5f1e1 175
176 package MooseX::Embiggen;
177
c8d5f1e1 178 use Moose::Exporter;
c8d5f1e1 179
180 use MooseX::Embiggen::Role::Meta::Class;
181 use MooseX::Embiggen::Role::Meta::Attribute;
6a7e3999 182 use MooseX::Embiggen::Role::Meta::Method::Constructor;
c8d5f1e1 183 use MooseX::Embiggen::Role::Object;
184
546a18e9 185 Moose::Exporter->setup_import_methods(
186 class_metaroles => {
187 class => ['MooseX::Embiggen::Role::Meta::Class'],
188 attribute => ['MooseX::Embiggen::Role::Meta::Attribute'],
189 constructor =>
190 ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
191 },
dae259f8 192 base_class_roles => ['MooseX::Embiggen::Role::Object'],
95056a1e 193 );
c8d5f1e1 194
0558aab4 195As you can see from this example, you can use L<Moose::Util::MetaRole>
c8d5f1e1 196to apply roles to any metaclass, as well as the base object class. If
197some other extension has already applied its own roles, they will be
198preserved when your extension applies its roles, and vice versa.
199
200=head2 Providing Sugar
201
546a18e9 202With L<Moose::Exporter>, you can also export your own sugar functions:
c8d5f1e1 203
204 package MooseX::Embiggen;
205
c8d5f1e1 206 use Moose::Exporter;
207
208 Moose::Exporter->setup_import_methods(
546a18e9 209 with_meta => ['embiggen'],
210 class_metaroles => {
211 class => ['MooseX::Embiggen::Role::Meta::Class'],
212 },
c8d5f1e1 213 );
214
c8d5f1e1 215 sub embiggen {
d5447d26 216 my $meta = shift;
217 $meta->embiggen(@_);
c8d5f1e1 218 }
219
220And then the consumer of your extension can use your C<embiggen> sub:
221
222 package Consumer;
223
b67e38c5 224 use Moose;
c8d5f1e1 225 use MooseX::Embiggen;
226
227 extends 'Thing';
228
229 embiggen ...;
230
231This can be combined with metaclass and base class roles quite easily.
232
8bb03292 233=head2 More advanced extensions
546a18e9 234
8bb03292 235Providing your extension simply as a set of traits that gets applied to the
236appropriate metaobjects is easy, but sometimes not sufficient. For instance,
237sometimes you need to supply not just a base object role, but an actual base
238object class (due to needing to interact with existing systems that only
239provide a base class). To write extensions like this, you will need to provide
240a custom C<init_meta> method in your exporter. For instance:
546a18e9 241
242 package MooseX::Embiggen;
243
546a18e9 244 use Moose::Exporter;
245
8bb03292 246 my ($import, $unimport, $init_meta) = Moose::Exporter->build_import_methods(
247 install => ['import', 'unimport'],
248 with_meta => ['embiggen'],
249 class_metaroles => {
250 class => ['MooseX::Embiggen::Role::Meta::Class'],
251 },
252 );
546a18e9 253
8bb03292 254 sub embiggen {
255 my $meta = shift;
256 $meta->embiggen(@_);
257 }
546a18e9 258
259 sub init_meta {
8bb03292 260 my $package = shift;
546a18e9 261 my %options = @_;
8bb03292 262 if (my $meta = Class::MOP::class_of($options{for_class})) {
263 if ($meta->isa('Class::MOP::Class')) {
264 my @supers = $meta->superclasses;
265 $meta->superclasses('MooseX::Embiggen::Base::Class')
266 if @supers == 1 && $supers[0] eq 'Moose::Object';
267 }
268 }
269 $package->$init_meta(%options);
546a18e9 270 }
271
8bb03292 272In the previous examples, C<init_meta> was generated for you, but here you must
273override it in order to add additional functionality. Some differences to note:
274
275=over 4
276
277=item C<build_import_methods> instead of C<setup_import_methods>
278
279C<build_import_methods> simply returns the C<import>, C<unimport>, and
280C<init_meta> methods, rather than installing them under the appropriate names.
281This way, you can write your own which wrap the existing functionality.
282C<build_import_methods> also takes an additional C<install> parameter, which
283tells it to just go ahead and install these methods (since we don't need to
284modify them).
285
286=item C<sub init_meta>
287
288Next, we must write our C<init_meta> wrapper. The important things to remember
289are that it is called as a method, and that C<%options> needs to be passed
290through to the existing implementation. Calling the base implementation just
291uses the C<$init_meta> subroutine reference that was returned by
292C<build_import_methods> earlier.
293
294=item Additional implementation
295
296This extension sets a different default base object class. To do so, it first
297checks to see if it's being applied to a class, and then checks to see if
298L<Moose::Object> is that class's only superclass, and if so, replaces that with
299the superclass that this extension requires.
300
301Note that two extensions that do this same thing will not work together
302properly (the second extension to be loaded won't see L<Moose::Object> as the
303base object, since it has already been overridden). This is why using a base
304object role is recommended for the general case.
305
306This C<init_meta> also works defensively, by only applying its functionality if
307a metaclass already exists. This makes sure it doesn't break with legacy
308extensions which override the metaclass directly (and so must be the first
309extension to initialize the metaclass). This is likely not necessary, since
310almost no extensions work this way anymore, but just provides an additional
311level of protection. The common case of C<use Moose; use MooseX::Embiggen;>
312is not affected regardless.
313
314=back
315
316This is just one example of what can be done with a custom C<init_meta> method.
317It can also be used for preventing an extension from being applied to a role,
318doing other kinds of validation on the class being applied to, or pretty much
319anything that would otherwise be done in an C<import> method.
e32cc906 320
0558aab4 321=head1 LEGACY EXTENSION MECHANISMS
c8d5f1e1 322
323Before the existence of L<Moose::Exporter> and
324L<Moose::Util::MetaRole>, there were a number of other ways to extend
325Moose. In general, these methods were less cooperative, and only
326worked well with a single extension.
327
0558aab4 328These methods include L<metaclass.pm|metaclass>, L<Moose::Policy>
329(which uses L<metaclass.pm|metaclass> under the hood), and various
330hacks to do what L<Moose::Exporter> does. Please do not use these for
331your own extensions.
c8d5f1e1 332
333Note that if you write a cooperative extension, it should cooperate
334with older extensions, though older extensions generally do not
8745c929 335cooperate with each other.
c8d5f1e1 336
337=head1 CONCLUSION
338
339If you can write your extension as one or more metaclass and base
340object roles, please consider doing so. Make sure to read the docs for
341L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
342
c8d5f1e1 343=cut