init_meta documentation
[gitmo/Moose.git] / lib / Moose / Cookbook / Extending / Recipe1.pod
1
2 =pod
3
4 =head1 NAME
5
6 Moose::Cookbook::Extending::Recipe1 - Moose extension overview
7
8 =head1 DESCRIPTION
9
10 Moose provides several ways in which extensions can hook into Moose
11 and change its behavior. Moose also has a lot of behavior that can be
12 changed. This recipe will provide an overview of each extension method
13 and give you some recommendations on what tools to use.
14
15 If you haven't yet read the recipes on metaclasses, go read those
16 first. You can't write Moose extensions without understanding the
17 metaclasses, and those recipes also demonstrate some basic extension
18 mechanisms, such as metaclass subclasses and traits.
19
20 =head2 Playing Nice With Others
21
22 One of the goals of this overview is to help you build extensions that
23 cooperate well with other extensions. This is especially important if
24 you plan to release your extension to CPAN.
25
26 Moose comes with several modules that exist to help your write
27 cooperative extensions. These are L<Moose::Exporter> and
28 L<Moose::Util::MetaRole>. By using these two modules, you will ensure
29 that your extension works with both the Moose core features and any
30 other CPAN extension using those modules.
31
32 =head1 PARTS OF Moose YOU CAN EXTEND
33
34 The types of things you might want to do in Moose extensions fall into
35 a few broad categories.
36
37 =head2 Metaclass Extensions
38
39 One way of extending Moose is by extending one or more Moose
40 metaclasses. For example, in L<Moose::Cookbook::Meta::Recipe4> we saw
41 a metaclass subclass that added a C<table> attribute to the
42 metaclass. If you were writing an ORM, this would be a logical
43 extension.
44
45 Many of the Moose extensions on CPAN work by providing an attribute
46 metaclass extension. For example, the L<MooseX::AttributeHelpers>
47 distribution provides a new attribute metaclass that lets you delegate
48 behavior to a non-object attribute (a hashref or simple number).
49
50 A metaclass extension can be packaged as a subclass or a
51 role/trait. If you can, we recommend using traits instead of
52 subclasses, since it's much easier to combine disparate traits then it
53 is to combine a bunch of subclasses.
54
55 When your extensions are implemented as roles, you can apply them with
56 the L<Moose::Util::MetaRole> module.
57
58 =head2 Providing Sugar Functions
59
60 As part of a metaclass extension, you may also want to provide some
61 sugar functions, just like L<Moose.pm|Moose> does. Moose provides a
62 helper module called L<Moose::Exporter> that makes this much
63 simpler. We will be use L<Moose::Exporter> in several of the extension
64 recipes.
65
66 =head2 Object Class Extensions
67
68 Another common Moose extension technique is to change the default
69 object class's behavior. For example, the L<MooseX::Singleton>
70 extension changes the behavior of your objects so that they are
71 singletons. The L<MooseX::StrictConstructor> extension makes the
72 constructor reject arguments which don't match its attributes.
73
74 Object class extensions often include metaclass extensions as well. In
75 particular, if you want your object extension to work when a class is
76 made immutable, you may need to extend some or all of the
77 L<Moose::Meta::Instance>, L<Moose::Meta::Method::Constructor>, and
78 L<Moose::Meta::Method::Destructor> objects.
79
80 The L<Moose::Util::MetaRole> module lets you apply roles to the base
81 object class, as well as the meta classes just mentioned.
82
83 =head2 Providing a Role
84
85 Some extensions come in the form of a role for you to consume. The
86 L<MooseX::Object::Pluggable> extension is a great example of this. In
87 fact, despite the C<MooseX> name, it does not actually change anything
88 about Moose's behavior. Instead, it is just a role that an object
89 which wants to be pluggable can consume.
90
91 If you are implementing this sort of extension, you don't need to do
92 anything special. You simply create a role and document that it should
93 be used via the normal C<with> sugar:
94
95    package MyApp::User;
96
97    use Moose;
98
99    with 'MooseX::My::Role';
100
101 =head2 New Types
102
103 Another common Moose extension is a new type for the Moose type
104 system. In this case, you simply create a type in your module. When
105 people load your module, the type is created, and they can refer to it
106 by name after that. The L<MooseX::Types::URI> and
107 L<MooseX::Types::DateTime> distributions are two good examples of how
108 this works. These both build on top of the L<MooseX::Types> extension.
109
110 =head1 ROLES VS TRAITS VS SUBCLASSES
111
112 It is important to understand that B<roles and traits are the same
113 thing>. A role can be used as a trait, and a trait is a role. The only
114 thing that distinguishes the two is that a trait is packaged in a way
115 that lets Moose resolve a short name to a class name. In other words,
116 with a trait, the caller can refer to it by a short name like "Big",
117 and Moose will resolve it to a class like
118 C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
119
120 See L<Moose::Cookbook::Meta::Recipe3> and
121 L<Moose::Cookbook::Meta::Recipe5> for examples of traits in action. In
122 particular, both of these recipes demonstrate the trait resolution
123 mechanism.
124
125 Implementing an extension as a (set of) metaclass or base object
126 role(s) will make your extension more cooperative. It is hard for an
127 end-user to effectively combine together multiple metaclass
128 subclasses, but it is very easy to combine roles.
129
130 =head1 USING YOUR EXTENSION
131
132 There are a number of ways in which an extension can be applied. In
133 some cases you can provide multiple ways of consuming your extension.
134
135 =head2 Extensions as Metaclass Traits
136
137 If your extension is available as a trait, you can ask end users to
138 simply specify it in a list of traits. Currently, this only works for
139 (class) metaclass and attribute metaclass traits:
140
141   use Moose -traits => [ 'Big', 'Blue' ];
142
143   has 'animal' => (
144       traits => [ 'Big', 'Blue' ],
145       ...
146   );
147
148 If your extension applies to any other metaclass, or the object base
149 class, you cannot use the trait mechanism.
150
151 The benefit of the trait mechanism is that is very easy to see where a
152 trait is applied in the code, and consumers have fine-grained control
153 over what the trait applies to. This is especially true for attribute
154 traits, where you can apply the trait to just one attribute in a
155 class.
156
157 =head2 Extensions as Metaclass (and Base Object) Subclasses
158
159 Moose does not provide any simple APIs for consumers to use a subclass
160 extension, except for attribute metaclasses. The attribute declaration
161 options include a C<metaclass> option a consumer of your extension can
162 use to specify your subclass.
163
164 This is one reason why implementing an extension as a subclass can be
165 a poor choice. However, you can force the use of certain subclasses at
166 import time by calling C<< Moose->init_meta >> for the caller, and
167 providing an alternate metaclass or base object class.
168
169 If you do want to do this, you should look at using L<Moose::Exporter>
170 to re-export the L<Moose.pm|Moose> sugar function. With
171 L<Moose::Exporter>, if your exporting class has an C<init_meta>
172 method, L<Moose::Exporter> makes sure that this C<init_meta> method
173 gets called when your class is imported.
174
175 Then in your C<init_meta> you can arrange for the caller to use your
176 subclasses:
177
178   package MooseX::Embiggen;
179
180   use Moose ();
181   use Moose::Exporter;
182
183   use MooseX::Embiggen::Meta::Class;
184   use MooseX::Embiggen::Object;
185
186   Moose::Exporter->setup_import_methods( also => 'Moose' );
187
188   sub init_meta {
189       shift;    # just your package name
190       my %options = @_;
191
192       return Moose->init_meta(
193           for_class  => $options{for_class},
194           metaclass  => 'MooseX::Embiggen::Meta::Class',
195           base_class => 'MooseX::Embiggen::Object',
196       );
197   }
198
199 NOTE: Make sure that your C<init_meta> returns the metaclass object, just as
200 C<< Moose->init_meta >> does.
201
202 =head2 Extensions as Metaclass (and Base Object) Roles
203
204 Implementing your extensions as metaclass roles makes your extensions
205 easy to apply, and cooperative with other role-based extensions for
206 metaclasses.
207
208 Just as with a subclass, you will probably want to package your
209 extensions for consumption with a single module that uses
210 L<Moose::Exporter>. However, in this case, you will use
211 L<Moose::Util::MetaRole> to apply all of your roles. The advantage of
212 using this module is that I<it preserves any subclassing or roles
213 already applied to the user's metaclasses>. This means that your
214 extension is cooperative I<by default>, and consumers of your
215 extension can easily use it with other role-based extensions.
216
217   package MooseX::Embiggen;
218
219   use Moose ();
220   use Moose::Exporter;
221   use Moose::Util::MetaRole;
222
223   use MooseX::Embiggen::Role::Meta::Class;
224   use MooseX::Embiggen::Role::Meta::Attribute;
225   use MooseX::Embiggen::Role::Meta::Method::Constructor;
226   use MooseX::Embiggen::Role::Object;
227
228   Moose::Exporter->setup_import_methods( also => 'Moose' );
229
230   sub init_meta {
231       shift;    # just your package name
232       my %options = @_;
233
234       Moose->init_meta(%options);
235
236       my $meta = Moose::Util::MetaRole::apply_metaclass_roles(
237           for_class       => $options{for_class},
238           metaclass_roles => ['MooseX::Embiggen::Role::Meta::Class'],
239           attribute_metaclass_roles =>
240               ['MooseX::Embiggen::Role::Meta::Attribute'],
241           constructor_class_roles =>
242               ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
243       );
244
245       Moose::Util::MetaRole::apply_base_class_roles(
246           for_class => $options{for_class},
247           roles     => ['MooseX::Embiggen::Role::Object'],
248       );
249
250       return $meta;
251   }
252
253 As you can see from this example, you can use L<Moose::Util::MetaRole>
254 to apply roles to any metaclass, as well as the base object class. If
255 some other extension has already applied its own roles, they will be
256 preserved when your extension applies its roles, and vice versa.
257
258 =head2 Providing Sugar
259
260 With L<Moose::Exporter>, you can also export your own sugar functions,
261 as well as those from other modules:
262
263   package MooseX::Embiggen;
264
265   use Moose ();
266   use Moose::Exporter;
267
268   Moose::Exporter->setup_import_methods(
269       with_caller => ['embiggen'],
270       also        => 'Moose',
271   );
272
273   sub init_meta { ... }
274
275   sub embiggen {
276       my $caller = shift;
277       $caller->meta()->embiggen(@_);
278   }
279
280 And then the consumer of your extension can use your C<embiggen> sub:
281
282   package Consumer;
283
284   use MooseX::Embiggen;
285
286   extends 'Thing';
287
288   embiggen ...;
289
290 This can be combined with metaclass and base class roles quite easily.
291
292 =head1 LEGACY EXTENSION MECHANISMS
293
294 Before the existence of L<Moose::Exporter> and
295 L<Moose::Util::MetaRole>, there were a number of other ways to extend
296 Moose. In general, these methods were less cooperative, and only
297 worked well with a single extension.
298
299 These methods include L<metaclass.pm|metaclass>, L<Moose::Policy>
300 (which uses L<metaclass.pm|metaclass> under the hood), and various
301 hacks to do what L<Moose::Exporter> does. Please do not use these for
302 your own extensions.
303
304 Note that if you write a cooperative extension, it should cooperate
305 with older extensions, though older extensions generally do not
306 cooperate with each other.
307
308 =head1 CONCLUSION
309
310 If you can write your extension as one or more metaclass and base
311 object roles, please consider doing so. Make sure to read the docs for
312 L<Moose::Exporter> and L<Moose::Util::MetaRole> as well.
313
314 =head1 AUTHOR
315
316 Dave Rolsky E<lt>autarch@urth.orgE<gt>
317
318 =head1 COPYRIGHT AND LICENSE
319
320 Copyright 2009 by Infinity Interactive, Inc.
321
322 L<http://www.iinteractive.com>
323
324 This library is free software; you can redistribute it and/or modify
325 it under the same terms as Perl itself.
326
327 =cut