determine prereqs automatically
[gitmo/MooseX-UndefTolerant.git] / lib / MooseX / UndefTolerant.pm
1 package MooseX::UndefTolerant;
2
3 use strict;
4 use warnings;
5
6 use Moose 0.89 qw();
7 use Moose::Exporter;
8
9 use MooseX::UndefTolerant::Attribute;
10 use MooseX::UndefTolerant::Class;
11 use MooseX::UndefTolerant::Constructor;
12
13
14 my %metaroles = (
15     class_metaroles => {
16         attribute => [ 'MooseX::UndefTolerant::Attribute' ],
17     }
18 );
19 if ( $Moose::VERSION < 1.9900 ) {
20     $metaroles{class_metaroles}{constructor} = [
21         'MooseX::UndefTolerant::Constructor',
22     ];
23 }
24 else {
25     $metaroles{class_metaroles}{class} = [
26         'MooseX::UndefTolerant::Class',
27     ];
28     $metaroles{role_metaroles} = {
29         applied_attribute => [
30             'MooseX::UndefTolerant::Attribute',
31         ],
32         role => [
33             'MooseX::UndefTolerant::Role',
34         ],
35         application_to_class => [
36             'MooseX::UndefTolerant::ApplicationToClass',
37         ],
38         application_to_role => [
39             'MooseX::UndefTolerant::ApplicationToRole',
40         ],
41     };
42 }
43
44
45 Moose::Exporter->setup_import_methods(%metaroles);
46
47 1;
48
49 # ABSTRACT: Make your attribute(s) tolerant to undef initialization
50
51 __END__
52
53 =head1 SYNOPSIS
54
55   package My::Class;
56
57   use Moose;
58   use MooseX::UndefTolerant;
59
60   has 'name' => (
61     is => 'ro',
62     isa => 'Str',
63     predicate => 'has_name'
64   );
65
66   # Meanwhile, under the city...
67
68   # Doesn't explode
69   my $class = My::Class->new(name => undef);
70   $class->has_name # False!
71
72 Or, if you only want one attribute to have this behaviour:
73
74   package My:Class;
75   use Moose;
76
77   use MooseX::UndefTolerant::Attribute;
78
79   has 'bar' => (
80       traits => [ qw(MooseX::UndefTolerant::Attribute)],
81       is => 'ro',
82       isa => 'Num',
83       predicate => 'has_bar'
84   );
85
86 =head1 DESCRIPTION
87
88 Loading this module in your L<Moose> class makes initialization of your
89 attributes tolerant of undef.  If you specify the value of undef to any of
90 the attributes they will not be initialized, effectively behaving as if you
91 had not provided a value at all.
92
93 You can also apply the 'UndefTolerant' trait to individual attributes. See
94 L<MooseX::UndefTolerant::Attribute> for details.
95
96 There will be no change in behaviour to any attribute with a type constraint
97 that accepts undef values (for example C<Maybe> types), as it is presumed that
98 since the type is already "undef tolerant", there is no need to avoid
99 initializing the attribute value with C<undef>.
100
101 As of Moose 1.9900, this module can also be used in a role, in which case all
102 of that role's attributes will be undef-tolerant.
103
104 =head1 MOTIVATION
105
106 I often found myself in this quandry:
107
108   package My:Class;
109   use Moose;
110
111   has 'foo' => (
112     is => 'ro',
113     isa => 'Str',
114   );
115
116   # ... then
117
118   my $foo = ... # get the param from something
119
120   my $class = My:Class->new(foo => $foo, bar => 123);
121
122 What if foo is undefined?  I didn't want to change my attribute to be
123 Maybe[Str] and I still want my predicate (C<has_foo>) to work.  The only
124 real solution was:
125
126   if(defined($foo)) {
127     $class = My:Class->new(foo => $foo, bar => 123);
128   } else {
129     $class = My:Class->new(bar => 123);
130   }
131
132 Or some type of codemulch using ternary conditionals.  This module allows you
133 to make your attributes more tolerant of undef so that you can keep the first
134 example: have your cake and eat it too!
135
136 =head1 PER ATTRIBUTE
137
138 See L<MooseX::UndefTolerant::Attribute>.
139
140 =head1 CAVEATS
141
142 This extension does not currently work in immutable classes when applying the
143 trait to some (but not all) attributes in the class. This is because the
144 inlined constructor initialization code currently lives in
145 L<Moose::Meta::Class>, not L<Moose::Meta::Attribute>. The good news is that
146 this is expected to be changing shortly.
147
148 =head1 ACKNOWLEDGEMENTS
149
150 Many thanks to the crew in #moose who talked me through this module:
151
152 Hans Dieter Pearcey (confound)
153
154 Jesse Luehrs (doy)
155
156 Tomas Doran (t0m)
157
158 Dylan Hardison (dylan)
159
160 Jay Shirley (jshirley)
161
162 Mike Eldridge (diz)
163
164 =cut