9094fbf2a9996a9ff51bae33f7f0307a1b0e9457
[gitmo/Moose.git] / lib / Moose / Meta / Attribute / Native.pm
1 package Moose::Meta::Attribute::Native;
2
3 our $VERSION   = '1.18';
4 $VERSION = eval $VERSION;
5 our $AUTHORITY = 'cpan:STEVAN';
6
7 my @trait_names = qw(Bool Counter Number String Array Hash Code);
8
9 for my $trait_name (@trait_names) {
10     my $trait_class = "Moose::Meta::Attribute::Native::Trait::$trait_name";
11     my $meta = Class::MOP::Class->initialize(
12         "Moose::Meta::Attribute::Custom::Trait::$trait_name"
13     );
14     if ($meta->find_method_by_name('register_implementation')) {
15         my $class = $meta->name->register_implementation;
16         Moose->throw_error(
17             "An implementation for $trait_name already exists " .
18             "(found '$class' when trying to register '$trait_class')"
19         );
20     }
21     $meta->add_method(register_implementation => sub {
22         # resolve_metatrait_alias will load classes anyway, but throws away
23         # their error message; we WANT to die if there's a problem
24         Class::MOP::load_class($trait_class);
25         return $trait_class;
26     });
27 }
28
29 1;
30
31 __END__
32
33 =pod
34
35 =head1 NAME
36
37 Moose::Meta::Attribute::Native - Delegate to native Perl types
38
39 =head1 SYNOPSIS
40
41   package MyClass;
42   use Moose;
43
44   has 'mapping' => (
45       traits  => ['Hash'],
46       is      => 'rw',
47       isa     => 'HashRef[Str]',
48       default => sub { {} },
49       handles => {
50           exists_in_mapping => 'exists',
51           ids_in_mapping    => 'keys',
52           get_mapping       => 'get',
53           set_mapping       => 'set',
54           set_quantity      => [ set => 'quantity' ],
55       },
56   );
57
58   my $obj = MyClass->new;
59   $obj->set_quantity(10);      # quantity => 10
60   $obj->set_mapping('foo', 4); # foo => 4
61   $obj->set_mapping('bar', 5); # bar => 5
62   $obj->set_mapping('baz', 6); # baz => 6
63
64   # prints 5
65   print $obj->get_mapping('bar') if $obj->exists_in_mapping('bar');
66
67   # prints 'quantity, foo, bar, baz'
68   print join ', ', $obj->ids_in_mapping;
69
70 =head1 DESCRIPTION
71
72 Native delegations allow you to delegate to native Perl data
73 structures as if they were objects. For example, in the L</SYNOPSIS> you can
74 see a hash reference being treated as if it has methods named C<exists()>,
75 C<keys()>, C<get()>, and C<set()>.
76
77 The delegation methods (mostly) map to Perl builtins and operators. The return
78 values of these delegations should be the same as the corresponding Perl
79 operation. Any deviations will be explicitly documented.
80
81 =head1 API
82
83 Native delegations are enabled by passing certain options to C<has> when
84 creating an attribute.
85
86 =head2 traits
87
88 To enable this feature, pass the appropriate name in the C<traits> array
89 reference for the attribute. For example, to enable this feature for hash
90 reference, we include C<'Hash'> in the list of traits.
91
92 =head2 isa
93
94 You will need to make sure that the attribute has an appropriate type. For
95 example, to use this with a Hash you must specify that your attribute is some
96 sort of C<HashRef>.
97
98 If you I<don't> specify a type, each trait has a default type it will use.
99
100 =head2 handles
101
102 This is just like any other delegation, but only a hash reference is allowed
103 when defining native delegations. The keys are the methods to be created in
104 the class which contains the attribute. The values are the methods provided by
105 the associated trait. Currying works the same way as it does with any other
106 delegation.
107
108 See the docs for each native trait for details on what methods are available.
109
110 =head2 is
111
112 Some traits provide a default C<is> for historical reasons. This behavior is
113 deprecated, and you are strongly encouraged to provide a value. If you don't
114 plan to read and write the attribute value directly, you can set C<< is =>
115 'bare' >> to prevent standard accessor generation.
116
117 =head2 default or builder
118
119 Some traits provide a default C<default> for historical reasons. This behavior
120 is deprecated, and you are strongly encouraged to provide a default value or
121 make the attribute required.
122
123 =head1 TRAITS FOR NATIVE DELEGATIONS
124
125 =over
126
127 =item L<Array|Moose::Meta::Attribute::Native::Trait::Array>
128
129     has 'queue' => (
130         traits  => ['Array'],
131         is      => 'ro',
132         isa     => 'ArrayRef[Str]',
133         default => sub { [] },
134         handles => {
135             add_item  => 'push',
136             next_item => 'shift',
137             # ...
138         }
139     );
140
141 =item L<Bool|Moose::Meta::Attribute::Native::Trait::Bool>
142
143     has 'is_lit' => (
144         traits  => ['Bool'],
145         is      => 'ro',
146         isa     => 'Bool',
147         default => 0,
148         handles => {
149             illuminate  => 'set',
150             darken      => 'unset',
151             flip_switch => 'toggle',
152             is_dark     => 'not',
153             # ...
154         }
155     );
156
157 =item L<Code|Moose::Meta::Attribute::Native::Trait::Code>
158
159     has 'callback' => (
160         traits  => ['Code'],
161         is      => 'ro',
162         isa     => 'CodeRef',
163         default => sub {
164             sub {'called'}
165         },
166         handles => {
167             call => 'execute',
168             # ...
169         }
170     );
171
172 =item L<Counter|Moose::Meta::Attribute::Native::Trait::Counter>
173
174     has 'counter' => (
175         traits  => ['Counter'],
176         is      => 'ro',
177         isa     => 'Num',
178         default => 0,
179         handles => {
180             inc_counter   => 'inc',
181             dec_counter   => 'dec',
182             reset_counter => 'reset',
183             # ...
184         }
185     );
186
187 =item L<Hash|Moose::Meta::Attribute::Native::Trait::Hash>
188
189     has 'options' => (
190         traits  => ['Hash'],
191         is      => 'ro',
192         isa     => 'HashRef[Str]',
193         default => sub { {} },
194         handles => {
195             set_option => 'set',
196             get_option => 'get',
197             has_option => 'exists',
198             # ...
199         }
200     );
201
202 =item L<Number|Moose::Meta::Attribute::Native::Trait::Number>
203
204     has 'integer' => (
205         traits  => ['Number'],
206         is      => 'ro',
207         isa     => 'Int',
208         default => 5,
209         handles => {
210             set => 'set',
211             add => 'add',
212             sub => 'sub',
213             mul => 'mul',
214             div => 'div',
215             mod => 'mod',
216             abs => 'abs',
217             # ...
218         }
219     );
220
221 =item L<String|Moose::Meta::Attribute::Native::Trait::String>
222
223     has 'text' => (
224         traits  => ['String'],
225         is      => 'ro',
226         isa     => 'Str',
227         default => q{},
228         handles => {
229             add_text     => 'append',
230             replace_text => 'replace',
231             # ...
232         }
233     );
234
235 =back
236
237 =head1 COMPATIBILITY WITH MooseX::AttributeHelpers
238
239 This feature used to be a separated CPAN distribution called
240 L<MooseX::AttributeHelpers>.
241
242 When the feature was incorporated into the Moose core, some of the API details
243 were changed. The underlying capabilities are the same, but some details of
244 the API were changed.
245
246 =head1 BUGS
247
248 See L<Moose/BUGS> for details on reporting bugs.
249
250 =head1 AUTHOR
251
252 Stevan Little E<lt>stevan@iinteractive.comE<gt>
253
254 B<with contributions from:>
255
256 Robert (rlb3) Boone
257
258 Paul (frodwith) Driver
259
260 Shawn (Sartak) Moore
261
262 Chris (perigrin) Prather
263
264 Robert (phaylon) Sedlacek
265
266 Tom (dec) Lanyon
267
268 Yuval Kogman
269
270 Jason May
271
272 Cory (gphat) Watson
273
274 Florian (rafl) Ragwitz
275
276 Evan Carroll
277
278 Jesse (doy) Luehrs
279
280 Jay Hannah
281
282 Robert Buels
283
284 =head1 COPYRIGHT AND LICENSE
285
286 Copyright 2007-2009 by Infinity Interactive, Inc.
287
288 L<http://www.iinteractive.com>
289
290 This library is free software; you can redistribute it and/or modify
291 it under the same terms as Perl itself.
292
293 =cut