Commit | Line | Data |
17e5e226 |
1 | package Moose::Meta::Attribute::Native; |
e3c07b19 |
2 | |
efa728b4 |
3 | our $VERSION = '1.15'; |
e3c07b19 |
4 | $VERSION = eval $VERSION; |
5 | our $AUTHORITY = 'cpan:STEVAN'; |
6 | |
cdf3cae6 |
7 | my @trait_names = qw(Bool Counter Number String Array Hash Code); |
fafc8b9b |
8 | |
9 | for my $trait_name (@trait_names) { |
c466e58f |
10 | my $trait_class = "Moose::Meta::Attribute::Native::Trait::$trait_name"; |
fafc8b9b |
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 | } |
e3c07b19 |
28 | |
e3c07b19 |
29 | 1; |
30 | |
31 | __END__ |
32 | |
33 | =pod |
34 | |
35 | =head1 NAME |
36 | |
e132fd56 |
37 | Moose::Meta::Attribute::Native - Delegate to native Perl types |
e3c07b19 |
38 | |
39 | =head1 SYNOPSIS |
40 | |
41 | package MyClass; |
42 | use Moose; |
e3c07b19 |
43 | |
44 | has 'mapping' => ( |
e132fd56 |
45 | traits => ['Hash'], |
46 | is => 'rw', |
47 | isa => 'HashRef[Str]', |
48 | default => sub { {} }, |
49 | handles => { |
e3c07b19 |
50 | exists_in_mapping => 'exists', |
51 | ids_in_mapping => 'keys', |
52 | get_mapping => 'get', |
53 | set_mapping => 'set', |
cb562ad2 |
54 | set_quantity => [ set => 'quantity' ], |
e3c07b19 |
55 | }, |
56 | ); |
57 | |
e3c07b19 |
58 | my $obj = MyClass->new; |
59 | $obj->set_quantity(10); # quantity => 10 |
2420461c |
60 | $obj->set_mapping('foo', 4); # foo => 4 |
61 | $obj->set_mapping('bar', 5); # bar => 5 |
62 | $obj->set_mapping('baz', 6); # baz => 6 |
e3c07b19 |
63 | |
2420461c |
64 | # prints 5 |
65 | print $obj->get_mapping('bar') if $obj->exists_in_mapping('bar'); |
e3c07b19 |
66 | |
2420461c |
67 | # prints 'quantity, foo, bar, baz' |
e3c07b19 |
68 | print join ', ', $obj->ids_in_mapping; |
69 | |
70 | =head1 DESCRIPTION |
71 | |
e132fd56 |
72 | Native delegations allow you to delegate to native Perl data |
73 | structure 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 |
e3c07b19 |
82 | |
e132fd56 |
83 | Native delegations are enabled by passing certain options to C<has> when |
84 | creating an attribute. |
e3c07b19 |
85 | |
e132fd56 |
86 | =head2 traits |
87b4e821 |
87 | |
e132fd56 |
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. |
e3c07b19 |
99 | |
100 | =head2 handles |
101 | |
e132fd56 |
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. |
e3c07b19 |
107 | |
e132fd56 |
108 | See the docs for each native trait for details on what methods are available. |
109 | |
b6bf6592 |
110 | =head2 default or builder |
111 | |
112 | Some traits provide a "default default" for historical reasons. This behavior |
113 | is deprecated, and you are strongly encouraged to provide a default value or |
114 | make the attribute required. |
115 | |
e132fd56 |
116 | =head1 TRAITS FOR NATIVE DELEGATIONS |
e3c07b19 |
117 | |
118 | =over |
119 | |
66cce11c |
120 | =item L<Array|Moose::Meta::Attribute::Native::Trait::Array> |
e3c07b19 |
121 | |
66cce11c |
122 | has 'queue' => ( |
e132fd56 |
123 | traits => ['Array'], |
124 | is => 'ro', |
125 | isa => 'ArrayRef[Str]', |
126 | default => sub { [] }, |
127 | handles => { |
66cce11c |
128 | add_item => 'push', |
129 | next_item => 'shift', |
39ab25ce |
130 | # ... |
52e0d71f |
131 | } |
132 | ); |
133 | |
66cce11c |
134 | =item L<Bool|Moose::Meta::Attribute::Native::Trait::Bool> |
e3c07b19 |
135 | |
66cce11c |
136 | has 'is_lit' => ( |
e132fd56 |
137 | traits => ['Bool'], |
138 | is => 'ro', |
139 | isa => 'Bool', |
140 | default => 0, |
141 | handles => { |
66cce11c |
142 | illuminate => 'set', |
143 | darken => 'unset', |
144 | flip_switch => 'toggle', |
145 | is_dark => 'not', |
146 | # ... |
147 | } |
148 | ); |
149 | |
150 | =item L<Code|Moose::Meta::Attribute::Native::Trait::Code> |
151 | |
66cce11c |
152 | has 'callback' => ( |
e132fd56 |
153 | traits => ['Code'], |
154 | is => 'ro', |
155 | isa => 'CodeRef', |
156 | default => sub { |
157 | sub {'called'} |
158 | }, |
159 | handles => { |
66cce11c |
160 | call => 'execute', |
39ab25ce |
161 | # ... |
52e0d71f |
162 | } |
163 | ); |
164 | |
c466e58f |
165 | =item L<Counter|Moose::Meta::Attribute::Native::Trait::Counter> |
e3c07b19 |
166 | |
52e0d71f |
167 | has 'counter' => ( |
e132fd56 |
168 | traits => ['Counter'], |
169 | is => 'ro', |
170 | isa => 'Num', |
171 | default => 0, |
172 | handles => { |
52e0d71f |
173 | inc_counter => 'inc', |
174 | dec_counter => 'dec', |
175 | reset_counter => 'reset', |
39ab25ce |
176 | # ... |
52e0d71f |
177 | } |
178 | ); |
179 | |
c466e58f |
180 | =item L<Hash|Moose::Meta::Attribute::Native::Trait::Hash> |
e3c07b19 |
181 | |
52e0d71f |
182 | has 'options' => ( |
e132fd56 |
183 | traits => ['Hash'], |
184 | is => 'ro', |
185 | isa => 'HashRef[Str]', |
186 | default => sub { {} }, |
187 | handles => { |
9958cbe1 |
188 | set_option => 'set', |
189 | get_option => 'get', |
190 | has_option => 'exists', |
39ab25ce |
191 | # ... |
52e0d71f |
192 | } |
193 | ); |
e3c07b19 |
194 | |
66cce11c |
195 | =item L<Number|Moose::Meta::Attribute::Native::Trait::Number> |
e3c07b19 |
196 | |
66cce11c |
197 | has 'integer' => ( |
e132fd56 |
198 | traits => ['Number'], |
199 | is => 'ro', |
200 | isa => 'Int', |
201 | default => 5, |
202 | handles => { |
66cce11c |
203 | set => 'set', |
204 | add => 'add', |
205 | sub => 'sub', |
206 | mul => 'mul', |
207 | div => 'div', |
208 | mod => 'mod', |
209 | abs => 'abs', |
754a4833 |
210 | # ... |
211 | } |
52e0d71f |
212 | ); |
e3c07b19 |
213 | |
66cce11c |
214 | =item L<String|Moose::Meta::Attribute::Native::Trait::String> |
b86a4688 |
215 | |
66cce11c |
216 | has 'text' => ( |
e132fd56 |
217 | traits => ['String'], |
218 | is => 'ro', |
219 | isa => 'Str', |
220 | default => q{}, |
221 | handles => { |
66cce11c |
222 | add_text => 'append', |
223 | replace_text => 'replace', |
754a4833 |
224 | # ... |
225 | } |
b86a4688 |
226 | ); |
227 | |
e3c07b19 |
228 | =back |
229 | |
e132fd56 |
230 | =head1 COMPATIBILITY WITH MooseX::AttributeHelpers |
231 | |
232 | This feature used to be a separated CPAN distribution called |
233 | L<MooseX::AttributeHelpers>. |
234 | |
235 | When the feature was incorporated into the Moose core, some of the API details |
236 | were changed. The underlying capabilities are the same, but some details of |
237 | the API were changed. |
238 | |
e3c07b19 |
239 | =head1 BUGS |
240 | |
d4048ef3 |
241 | See L<Moose/BUGS> for details on reporting bugs. |
e3c07b19 |
242 | |
243 | =head1 AUTHOR |
244 | |
245 | Stevan Little E<lt>stevan@iinteractive.comE<gt> |
246 | |
247 | B<with contributions from:> |
248 | |
249 | Robert (rlb3) Boone |
250 | |
251 | Paul (frodwith) Driver |
252 | |
253 | Shawn (Sartak) Moore |
254 | |
255 | Chris (perigrin) Prather |
256 | |
257 | Robert (phaylon) Sedlacek |
258 | |
259 | Tom (dec) Lanyon |
260 | |
261 | Yuval Kogman |
262 | |
263 | Jason May |
264 | |
265 | Cory (gphat) Watson |
266 | |
267 | Florian (rafl) Ragwitz |
268 | |
269 | Evan Carroll |
270 | |
271 | Jesse (doy) Luehrs |
272 | |
52a98907 |
273 | Jay Hannah |
274 | |
275 | Robert Buels |
276 | |
e3c07b19 |
277 | =head1 COPYRIGHT AND LICENSE |
278 | |
279 | Copyright 2007-2009 by Infinity Interactive, Inc. |
280 | |
281 | L<http://www.iinteractive.com> |
282 | |
283 | This library is free software; you can redistribute it and/or modify |
284 | it under the same terms as Perl itself. |
285 | |
286 | =cut |