File Coverage

blib/lib/MooseX/AttributeInflate.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package MooseX::AttributeInflate;
2 2     2   65883 use warnings;
  2         7  
  2         61  
3 2     2   10 use strict;
  2         4  
  2         65  
4 2     2   944 use Moose ();
  0            
  0            
5             use Moose::Exporter ();
6              
7             our $VERSION = '0.03';
8              
9             Moose::Exporter->setup_import_methods(
10             with_caller => ['has_inflated'],
11             also => 'Moose',
12             );
13              
14             sub has_inflated {
15             my $caller = shift;
16             my $name = shift;
17             my %options = @_;
18             $options{traits} ||= [];
19             unshift @{$options{traits}}, 'Inflated';
20             Class::MOP::Class->initialize($caller)->add_attribute($name, %options);
21             }
22              
23             =head1 NAME
24              
25             MooseX::AttributeInflate - Auto-inflate your Moose attribute objects
26              
27             =head1 VERSION
28              
29             Version 0.03
30              
31             =head1 SYNOPSIS
32              
33             Lazily constructs ("inflates") an object attribute, optionally using constant
34             parameters.
35              
36             package MyClass;
37             use MooseX::AttributeInflate;
38              
39             has_inflated 'helper' => (
40             is => 'ro', isa => 'MyHelper'
41             );
42              
43             # OR, explicitly
44              
45             has 'helper' => (
46             is => 'ro', isa => 'MyHelper',
47             traits => [qw/Inflated/],
48             inflate_args => [],
49             inflate_method => 'new',
50             );
51              
52             my $obj = MyClass->new();
53             $obj->helper->help();
54              
55             =head1 DESCRIPTION
56              
57             For each attribute defined with L</has_inflated>, this module overrides the
58             C<default> for that attribute, calling instead that attribute's type's
59             constructor. The construction is done lazily unless overriden with
60             C<< lazy => 0 >>.
61              
62             See L</has_inflated> for options and more detail.
63              
64             Construction only works with objects; an exception will be thrown if the
65             C<isa> type of this attribute is not a decendant of C<Object> (this includes
66             C<ArrayRef> and C<HashRef> types).
67              
68             Alternatively, you may use the attribute trait C<Inflated> to compose an
69             attribute with other attribute trais.
70              
71             =head1 EXPORTS
72              
73             =head2 has_inflated
74              
75             Just like Moose's C<has>, but applies the attribute trait C<Inflated> and
76             defaults C<lazy> to be on. See L<Moose/EXPORTED FUNCTIONS> for more detail on
77             C<has>.
78              
79             If C<lazy_build> is defined, the canonical build method (e.g.
80             C<_build_helper>) B<IS NOT> called. Otherwise, C<lazy_build> works as usual,
81             setting C<required> and installing a clearer and predicate.
82              
83             Additional options:
84              
85             =over 4
86              
87             =item lazy
88              
89             Defaults on, but can be turned off with C<< lazy => 0 >>.
90              
91             =item lazy_build
92              
93             Just like L<Moose>'s C<lazy_build>, but does not call the canonical builder
94             method (e.g. C<_build_$name>).
95              
96             =item inflate_method
97              
98             The name of the constructor to use. Defaults to 'new'.
99              
100             =item inflate_args
101              
102             The arguments to pass to the constructor. Defaults to an empty list.
103              
104             =back
105              
106             =head1 SEE ALSO
107              
108             L<MooseX::CurriedHandles> - combine with this module for auto-inflating moose curry!
109              
110             L<http://github.com/stash/moosex-attributeinflate/> - Github repository
111              
112             =head1 AUTHOR
113              
114             Stash <jstash+cpan@gmail.com>
115              
116             =head1 BUGS
117              
118             Please report any bugs or feature requests to C<bug-moosex-attrinflate at rt.cpan.org>, or through
119             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=MooseX-AttributeInflate>. I will be notified, and then you'll
120             automatically be notified of progress on your bug as I make changes.
121              
122             =head1 SUPPORT
123              
124             You can find documentation for this module with the perldoc command.
125              
126             perldoc MooseX::AttributeInflate
127              
128              
129             You can also look for information at:
130              
131             =over 4
132              
133             =item * C<#moose> on irc.perl.org
134              
135             L<irc://irc.perl.org#moose>
136              
137             =item * RT: CPAN's request tracker
138              
139             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=MooseX-AttributeInflate>
140              
141             =item * AnnoCPAN: Annotated CPAN documentation
142              
143             L<http://annocpan.org/dist/MooseX-AttributeInflate>
144              
145             =item * CPAN Ratings
146              
147             L<http://cpanratings.perl.org/d/MooseX-AttributeInflate>
148              
149             =item * Search CPAN
150              
151             L<http://search.cpan.org/dist/MooseX-AttributeInflate>
152              
153             =back
154              
155              
156             =head1 ACKNOWLEDGEMENTS
157              
158             C<konobi> for Meta-advice and CPAN help
159              
160             C<perigrin>, C<doy>, C<Sartak> and other C<#moose> folks for suggestions & patches.
161              
162             =head1 COPYRIGHT & LICENSE
163              
164             Copyright 2009 Jeremy Stashewsky
165              
166             Copyright 2009 Socialtext Inc., all rights reserved.
167              
168             This program is free software; you can redistribute it and/or modify it
169             under the same terms as Perl itself.
170              
171             =cut
172              
173             package MooseX::Meta::Attribute::Trait::Inflated;
174             use Moose::Role;
175             use Moose::Util::TypeConstraints ();
176              
177             has 'inflate_args' => (
178             is => 'rw', isa => 'ArrayRef',
179             predicate => 'has_inflate_args'
180             );
181             has 'inflate_method' => (
182             is => 'rw', isa => 'Str',
183             default => 'new'
184             );
185              
186             sub inflate {
187             my $self = shift;
188             my $class = $self->type_constraint->name;
189             my $ctor = $self->inflate_method;
190             return $class->$ctor($self->has_inflate_args ? @{$self->inflate_args} : ());
191             }
192              
193             around 'new' => sub {
194             my $code = shift;
195              
196             my $class = shift;
197             my $name = shift;
198             my %options = @_;
199              
200             $options{lazy} = 1 unless exists $options{lazy};
201              
202             if ($options{lazy_build}) {
203             delete $options{lazy_build};
204             delete $options{builder};
205             $options{lazy} = 1;
206             $options{required} = 1;
207             if ($name =~ /^_/) {
208             $options{predicate} ||= "_has$name";
209             $options{clearer} ||= "_clear$name";
210             }
211             else {
212             $options{predicate} ||= "has_$name";
213             $options{clearer} ||= "clear_$name";
214             }
215             }
216             $options{required} = 1;
217             $options{default} = sub {
218             $_[0]->meta->get_attribute($name)->inflate()
219             };
220              
221             my $self = $class->$code($name,%options);
222              
223             my $type = $self->type_constraint;
224             confess "type constraint isn't a subtype of Object"
225             unless $type->is_subtype_of('Object');
226              
227             return $self;
228             };
229              
230             if ($Moose::VERSION < 1.09) {
231             around 'legal_options_for_inheritance' => sub {
232             my $code = shift;
233             my $self = shift;
234             return ($self->$code(@_), 'inflate_args', 'inflate_method')
235             };
236             }
237              
238              
239             no Moose::Role;
240              
241             package # happy PAUSE
242             Moose::Meta::Attribute::Custom::Trait::Inflated;
243             sub register_implementation { 'MooseX::Meta::Attribute::Trait::Inflated' }
244              
245             1;