Add another TODO recipe, for hooking into the immutabilization
[gitmo/Moose.git] / lib / Moose / Cookbook / Extending / Recipe2.pod
CommitLineData
6fa0a13f 1
2=pod
3
4=head1 NAME
5
6Moose::Cookbook::Extending::Recipe2 - Acting like Moose.pm and providing sugar Moose-style
7
8=head1 SYNOPSIS
9
10 package MyApp::Mooseish;
11
12 use strict;
13 use warnings;
14
15 our @EXPORT = qw( has_table );
16
17 use base 'Exporter';
18 use Class::MOP;
19 use Moose ();
20
21 sub import {
22 my $caller = caller();
23
24 return if $caller eq 'main';
25
26 Moose::init_meta( $caller,
27 undef, # object base class
28 'MyApp::Meta::Class',
29 );
30
31 Moose->import( { into => $caller }, @_ );
32
33 __PACKAGE__->export_to_level( 1, @_ );
34 }
35
36 sub unimport {
37 my $caller = caller();
38
39 no strict 'refs';
40 foreach my $name (@EXPORT) {
41 if ( defined &{ $caller . '::' . $name } ) {
42 my $keyword = \&{ $caller . '::' . $name };
43
44 my ($pkg_name) = Class::MOP::get_code_info($keyword);
45
46 next if $pkg_name ne __PACKAGE__;
47
48 delete ${ $caller . '::' }{$name};
49 }
50 }
51
52 Moose::unimport( { into_level => 1 } );
53 }
54
55 sub has_table {
56 my $caller = caller();
57
58 $caller->meta()->table(shift);
59 }
60
61=head1 DESCRIPTION
62
63The code above shows what it takes to provide an import-based
64interface just like C<Moose.pm>.
65
66Given the above code, you can now replace all instances of C<use
67Moose> with C<use MyApp::Mooseish>. Similarly, C<no Moose> is now
68replaced with C<no MyApp::Mooseish>.
69
70=head1 WARNING
71
72This recipe covers a fairly undocumented and ugly part of Moose, and
73the techniques described here may be deprecated in a future
74release. If this happens, there will be plenty of warning, as a number
75of C<MooseX> modules on CPAN already use these techniques.
76
77=head1 HOW IT IS USED
78
79The purpose of all this code is to provide a Moose-like
80interface. Here's what it would look like in actual use:
81
82 package MyApp::User;
83
84 use MyApp::Mooseish;
85
86 has_table 'User';
87
88 has 'username';
89 has 'password';
90
91 sub login { ... }
92
93 no MyApp::Mooseish;
94
95All of the normal Moose sugar (C<has()>, C<with()>, etc) is available
96when you C<use MyApp::Mooseish>.
97
98=head1 DISSECTION
99
100The first bit of magic is the call to C<Moose::init_meta()>. What this
101does is create a metaclass for the specified class. Normally, this is
102called by C<Moose.pm> in its own C<import()> method. However, we can
103call it first in order to provide an alternate metaclass class. We
104could also provide an alternate base object class to replace
105C<Moose::Object> (see L<Moose::Cookbook::Extending::Recipe1> for an
106example).
107
108The C<Moose::init_meta()> call takes three parameters. The first is
109the class for which we are initializing a metaclass object. The second
110is the base object, which is L<Moose::Object> by default. The third
111argument is the metaclass class, which is C<Moose::Meta::Class> by
112default.
113
114The next bit of magic is this:
115
116 Moose->import( { into => $caller } );
117
118This use of "into" is actually part of the C<Sub::Exporter> API, which
119C<Moose.pm> uses internally to export things like C<has()> and
120C<extends()>.
121
122Finally, we call C<< __PACKAGE__->export_to_level() >>. This method
123actually comes from C<Exporter>.
124
125This is all a bit fragile since it doesn't stack terribly well. You
126can basically only have one Moose-alike module. This may be fixed in
127the still-notional C<MooseX::Exporter> module someday.
128
129The C<unimport()> subroutine is basically a copy of the C<unimport()>
130from C<Moose.pm>. You can copy this verbatim into your code. Again,
131this doesn't stack well.
132
133Finally, we have our C<has_table()> subroutine. This provides a bit of
134sugar that looks a lot like C<has()>.
135
136=head1 AUTHOR
137
138Dave Rolsky E<lt>autarch@urth.orgE<gt>
139
140=head1 COPYRIGHT AND LICENSE
141
142Copyright 2006-2008 by Infinity Interactive, Inc.
143
144L<http://www.iinteractive.com>
145
146This library is free software; you can redistribute it and/or modify
147it under the same terms as Perl itself.
148
149=pod