0.002 added the constructor functionality and removed auto_install
[gitmo/MooseX-Emulate-Class-Accessor-Fast.git] / lib / MooseX / Emulate / Class / Accessor / Fast.pm
CommitLineData
c5a105b3 1package MooseX::Emulate::Class::Accessor::Fast;
2
e579fc46 3use Moose::Role;
c5a105b3 4
6b8ba79f 5our $VERSION = '0.00200';
c5a105b3 6
7=head1 NAME
8
9MooseX::Emulate::Class::Accessor::Fast -
10 Emulate Class::Accessor::Fast behavior using Moose attributes
11
12=head1 SYNOPSYS
13
14 package MyClass;
e579fc46 15 Use Moose;
16
17 with 'MooseX::Emulate::Class::Accessor::Fast';
c5a105b3 18
c5a105b3 19
20 #fields with readers and writers
21 __PACKAGE__->mk_accessors(qw/field1 field2/);
22 #fields with readers only
23 __PACKAGE__->mk_accessors(qw/field3 field4/);
24 #fields with writers only
25 __PACKAGE__->mk_accessors(qw/field5 field6/);
26
27
28=head1 DESCRIPTION
29
30This module attempts to emulate the behavior of L<Class::Accessor::Fast> as
31accurately as possible using the Moose attribute system. The public API of
32C<Class::Accessor::Fast> is wholly supported, but the private methods are not.
33If you are only using the public methods (as you should) migration should be a
e579fc46 34matter of switching your C<use base> line to a C<with> line.
c5a105b3 35
36While I have attempted to emulate the behavior of Class::Accessor::Fast as closely
37as possible bugs may still be lurking in edge-cases.
38
39=head1 BEHAVIOR
40
41Simple documentation is provided here for your convenience, but for more thorough
42documentation please see L<Class::Accessor::Fast> and L<Class::Accessor>.
43
44=head2 A note about introspection
45
46Please note that, at this time, the C<is> flag attribute is not being set. To
47determine the C<reader> and C<writer> methods using introspection in later versions
48of L<Class::MOP> ( > 0.38) please use the C<get_read_method> and C<get_write_method>
49methods in L<Class::MOP::Attribute>. Example
50
51 # with Class::MOP <= 0.38
52 my $attr = $self->meta->find_attribute_by_name($field_name);
53 my $reader_method = $attr->reader || $attr->accessor;
54 my $writer_method = $attr->writer || $attr->accessor;
55
56 # with Class::MOP > 0.38
57 my $attr = $self->meta->find_attribute_by_name($field_name);
58 my $reader_method = $attr->get_read_method;
59 my $writer_method = $attr->get_write_method;
60
61=head1 METHODS
62
6b8ba79f 63=head2 new %args
64
65Extend the default Moose constructor to emulate the behavior of C::A::F and
66store arguments in the instance hashref.
67
68=cut
69
70around new => sub{
71 my $orig = shift;
72 my $class = shift;
73 my %args;
74 if (scalar @_ == 1 && defined $_[0] && ref($_[0]) eq 'HASH') {
75 %args = %{$_[0]};
76 } else {
77 %args = @_;
78 }
79 my $self = $class->$orig(@_);
80 my @extra = grep { !exists($self->{$_}) } keys %args;
81 @{$self}{@extra} = @args{@extra};
82 return $self;
83};
84
c5a105b3 85=head2 mk_accessors @field_names
86
87Create read-write accessors. An attribute named C<$field_name> will be created.
88The name of the c<reader> and C<writer> methods will be determined by the return
89value of C<accessor_name_for> and C<mutator_name_for>, which by default return the
90name passed unchanged. If the accessor and mutator names are equal the C<accessor>
91attribute will be passes to Moose, otherwise the C<reader> and C<writer> attributes
92will be passed. Please see L<Class::MOP::Attribute> for more information.
93
94=cut
95
96sub mk_accessors{
97 my $self = shift;
98 my $meta = $self->meta;
99 for my $attr_name (@_){
100 my $reader = $self->accessor_name_for($attr_name);
101 my $writer = $self->mutator_name_for( $attr_name);
102 #dont overwrite existing methods
103 my @opts = $reader eq $writer ?
104 ( $self->can($reader) ? () : (accessor => $reader) ) :
105 (
106 ( $self->can($reader) ? () : (reader => $reader) ),
107 ( $self->can($writer) ? () : (writer => $writer) ),
108 );
109 $meta->add_attribute($attr_name, @opts);
110
111 $meta->add_method("_${attr_name}_accessor", $self->can($reader) )
112 if($reader eq $attr_name && !$self->can("_${attr_name}_accessor") );
113 }
114}
115
116=head2 mk_ro_accessors @field_names
117
118Create read-only accessors.
119
120=cut
121
122sub mk_ro_accessors{
123 my $self = shift;
124 my $meta = $self->meta;
125 for my $attr_name (@_){
126 my $reader = $self->accessor_name_for($attr_name);
127 $meta->add_attribute($attr_name,
128 $self->can($reader) ? () : (reader => $reader) );
129 $meta->add_method("_${attr_name}_accessor", $meta->find_method_by_name($reader))
130 if($reader eq $attr_name && !$self->can("_${attr_name}_accessor") );
131 }
132}
133
134=head2 mk_ro_accessors @field_names
135
136Create write-only accessors.
137
138=cut
139
140#this is retarded.. but we need it for compatibility or whatever.
141sub mk_wo_accessors{
142 my $self = shift;
143 my $meta = $self->meta;
144 for my $attr_name (@_){
145 my $writer = $self->mutator_name_for($attr_name);
146 $meta->add_attribute($attr_name, $self->can($writer) ? () : (writer => $writer) );
147 $meta->add_method("_${attr_name}_accessor", $meta->find_method_by_name($writer))
148 if($writer eq $attr_name && !$self->can("_${attr_name}_accessor") );
149 }
150}
151
152=head2 follow_best_practices
153
154Preface readers with 'get_' and writers with 'set_'.
155See original L<Class::Accessor> documentation for more information.
156
157=cut
158
159sub follow_best_practice{
160 my $self = shift;
161 my $meta = $self->meta;
162
163 $meta->remove_method('mutator_name_for');
164 $meta->remove_method('accessor_name_for');
165 $meta->add_method('mutator_name_for', sub{ return "set_".$_[1] });
166 $meta->add_method('accessor_name_for', sub{ return "get_".$_[1] });
167}
168
169=head2 mutator_name_for
170
171=head2 accessor_name_for
172
173See original L<Class::Accessor> documentation for more information.
174
175=cut
176
177sub mutator_name_for{ return $_[1] }
178sub accessor_name_for{ return $_[1] }
179
180=head2 set
181
182See original L<Class::Accessor> documentation for more information.
183
184=cut
185
186sub set{
187 my $self = shift;
188 my $k = shift;
189 confess "Wrong number of arguments received" unless scalar @_;
190
191 #my $writer = $self->mutator_name_for( $k );
192 confess "No such attribute '$k'"
193 unless ( my $attr = $self->meta->find_attribute_by_name($k) );
194 my $writer = $attr->writer || $attr->accessor;
195 $self->$writer(@_ > 1 ? [@_] : @_);
196}
197
198=head2 get
199
200See original L<Class::Accessor> documentation for more information.
201
202=cut
203
204sub get{
205 my $self = shift;
206 confess "Wrong number of arguments received" unless scalar @_;
207
208 my @values;
209 #while( my $attr = $self->meta->find_attribute_by_name( shift(@_) ){
210 for( @_ ){
211 confess "No such attribute '$_'"
212 unless ( my $attr = $self->meta->find_attribute_by_name($_) );
213 my $reader = $attr->reader || $attr->accessor;
214 @_ > 1 ? push(@values, $self->$reader) : return $self->$reader;
215 }
216
217 return @values;
218}
219
2201;
221
222=head2 meta
223
224See L<Moose::Meta::Class>.
225
226=cut
227
228=head1 SEE ALSO
229
230L<Moose>, L<Moose::Meta::Attribute>, L<Class::Accessor>, L<Class::Accessor::Fast>,
231L<Class::MOP::Attribute>, L<MooseX::Adopt::Class::Accessor::Fast>
232
233=head1 AUTHOR
234
235Guillermo Roditi (groditi) <groditi@cpan.org>
236
237=head1 LICENSE
238
239You may distribute this code under the same terms as Perl itself.
240
241=cut