1 package MooseX::UndefTolerant;
9 use MooseX::UndefTolerant::Attribute;
10 use MooseX::UndefTolerant::Class;
11 use MooseX::UndefTolerant::Constructor;
15 base_class_roles => [ 'MooseX::UndefTolerant::Object' ],
17 attribute => [ 'MooseX::UndefTolerant::Attribute' ],
20 if ( $Moose::VERSION < 1.9900 ) {
21 $metaroles{class_metaroles}{constructor} = [
22 'MooseX::UndefTolerant::Constructor',
26 $metaroles{class_metaroles}{class} = [
27 'MooseX::UndefTolerant::Class',
29 $metaroles{role_metaroles} = {
30 applied_attribute => [
31 'MooseX::UndefTolerant::Attribute',
34 'MooseX::UndefTolerant::Role',
36 application_to_class => [
37 'MooseX::UndefTolerant::ApplicationToClass',
39 application_to_role => [
40 'MooseX::UndefTolerant::ApplicationToRole',
46 Moose::Exporter->setup_import_methods(%metaroles);
50 # ABSTRACT: Make your attribute(s) tolerant to undef initialization
59 use MooseX::UndefTolerant;
64 predicate => 'has_name'
67 # Meanwhile, under the city...
70 my $class = My::Class->new(name => undef);
71 $class->has_name # False!
73 Or, if you only want one attribute to have this behaviour:
78 use MooseX::UndefTolerant::Attribute;
81 traits => [ qw(MooseX::UndefTolerant::Attribute)],
84 predicate => 'has_bar'
89 Loading this module in your L<Moose> class makes initialization of your
90 attributes tolerant of undef. If you specify the value of undef to any of
91 the attributes they will not be initialized, effectively behaving as if you
92 had not provided a value at all. Such values are also cleaned from BUILDARGS.
94 You can also apply the 'UndefTolerant' trait to individual attributes. See
95 L<MooseX::UndefTolerant::Attribute> for details.
97 There will be no change in behaviour to any attribute with a type constraint
98 that accepts undef values (for example C<Maybe> types), as it is presumed that
99 since the type is already "undef tolerant", there is no need to avoid
100 initializing the attribute value with C<undef>.
102 As of Moose 1.9900, this module can also be used in a role, in which case all
103 of that role's attributes will be undef-tolerant.
107 I often found myself in this quandry:
119 my $foo = ... # get the param from something
121 my $class = My:Class->new(foo => $foo, bar => 123);
123 What if foo is undefined? I didn't want to change my attribute to be
124 Maybe[Str] and I still want my predicate (C<has_foo>) to work. The only
128 $class = My:Class->new(foo => $foo, bar => 123);
130 $class = My:Class->new(bar => 123);
133 Or some type of codemulch using ternary conditionals. This module allows you
134 to make your attributes more tolerant of undef so that you can keep the first
135 example: have your cake and eat it too!
139 See L<MooseX::UndefTolerant::Attribute>.
143 This extension does not currently work in immutable classes when applying the
144 trait to a specific attributes in the class, as opposed to the class itself.
145 This is because the inlined constructor initialization code currently lives in
146 L<Moose::Meta::Class>, not L<Moose::Meta::Attribute>. The good news is that
147 this is expected to be changing shortly.
149 Also, BUILDARGS cannot be cleaned up if the entire class is not made undef
150 tolerant, as attribute traits cannot modify class constructor behaviour.
152 =head1 ACKNOWLEDGEMENTS
154 Many thanks to the crew in #moose who talked me through this module:
156 Hans Dieter Pearcey (confound)
162 Dylan Hardison (dylan)
164 Jay Shirley (jshirley)