6 Moose::Cookbook::Snack::ArrayRef - (Ab)using the ArrayRef type constraint
7 provided by the L<Moose::Util::TypeConstraint> and/or
8 L<Moose::Util::TypeConstraints::OptimizedConstraints> classes.
15 has 'name' => (is => 'rw', required => 1);
16 has 'species' => (is => 'rw', required => 1);
18 package ProduceStoreArray;
20 use Moose::Util::TypeConstraints;
22 has 'fruit_aisle' => (isa => 'ArrayRef[Fruit]', is => 'rw');
26 # we need something to put in the fruit aisle
27 my $orange = Fruit->new(name => 'orange', species => 'C. sinensis');
28 my $apple = Fruit->new(name => 'apple', species => 'M. domestica');
29 my @fruit = ($apple, $orange);
30 my $store = ProduceStoreArray->new(fruit_aisle => \@fruit);
34 The ArrayRef type constraint is used to store a reference to a Perl list or
35 array variable as an attribute of a Moose object.
39 The code in this document will work on Moose as advertised, but the developers
40 strongly recommend using something like L<Moose::Autobox> or
41 L<MooseX::AttributeHelpers> when working with array references in order to
42 help keep your Moose objects nice and encapsulated.
44 =head2 Assigning arrays to an ArrayRef attribute
46 Once a Moose-based object with an C<ArrayRef> attribute has been created, you
47 can pass an array (by reference) to that object attribute using that
48 attribute's accessor. This is how we assign the apple and orange to the
49 store's C<fruit_aisle> C<ArrayRef> attribute, we pass an array containing both
50 objects by reference to the C<fruit_aisle> attribute:
52 my @fruit = ($apple, $orange);
53 my $store = ProduceStoreArray->new(fruit_aisle => \@fruit);
55 Or you can pass an anonymous array to the C<ArrayRef> attribute as well. If
56 you created two new objects, C<$grape> and C<$tomato>, and assigned them to
57 the C<ArrayRef>, they would replace the apple and the orange in the store's
60 $store->fruit_aisle( [$grape, $tomato] );
62 Our C<fruit_aisle> C<ArrayRef> is parameterized, meaning, that the
63 C<fruit_aisle> C<ArrayRef> can contain nothing but C<Fruit> objects as array
64 values. If you try to pass in a reference to a array using C<Str> objects as
65 array values for example, Moose will complain:
67 Attribute (fruit_aisle) does not pass the type constraint (ArrayRef[Str])
69 =head2 Dumping the contents of an ArrayRef
71 In order to dump the contents of a C<ArrayRef> object attribute, you must first
72 de-reference the C<ArrayRef>, and then enumerate over it's keys. You can add
73 this method for showing the store's inventory to the C<ProduceStoreArray>
74 object shown in the SYNOPSIS:
78 foreach my $item ( @{$self->fruit_aisle} ) {
79 # access each Fruit object
80 } # foreach my $item ( @{$self->fruit_aisle} )
83 =head2 Assigning arrays to an ArrayRef will overwrite existing arrays
85 Once you create an object containing a C<ArrayRef> attribute, if you assign a
86 new array reference to that attribute, it will replace any existing array
89 # replace existing inventory
90 my $grape = Fruit->new(name => 'grape', species => 'V. vinifera');
91 my $tomato = Fruit->new(name => 'tomato', species => 'S. lycopersicum');
92 $store->fruit_aisle( [$grape, $tomato] );
94 =head2 Appending/Deleting values to/from an ArrayRef
96 In order to append new elements to an array referred to by the C<ArrayRef>
97 attribute, you will need to make a copy of the array first, add your new array
98 elements, then assign your modified copy back to the C<ArrayRef> attribute:
100 my @fruit_aisle_copy = @{$store->fruit_aisle};
101 my $avocado = Fruit->new(name => 'avocado', species => 'P. americana');
102 push(@fruit_aisle_copy, $avocado);
103 $store->fruit_aisle( \@fruit_aisle_copy );
105 And here's an example of deleting an object stored in an ArrayRef:
107 my @fruit_aisle_copy = @{$store->fruit_aisle};
108 # new array to hold the fruit objects that won't be deleted
109 my @reworked_fruit_aisle;
110 for my $fruit_obj ( @fruit_aisle_copy ) {
111 if ( $fruit_obj->name ne 'tomato' ) {
112 push(@reworked_fruit_aisle, $fruit_obj);
113 } # if ( $fruit_obj->name ne 'tomato' )
114 } # for my $fruit_obj ( @fruit_aisle_copy )
115 $store->fruit_aisle( \@reworked_fruit_aisle );
117 Putting the above code into their own object methods would make appending to or deleting from an C<ArrayRef> a trivial operation.
119 =head2 Clearing an ArrayRef
121 Assigning C<undef> to clear an C<ArrayRef> will not work because the attribute
122 was originally defined with a type constraint, meaning that attribute must have
123 0 or more of that type of value to be valid. C<undef> in Perl is not a value,
124 so it won't work for clearing the C<ArrayRef>.
126 If you assign an empty anonymous hash to a C<ArrayRef> attribute, this will
127 clear out that attribute yet still satisfy the type constraint.
129 # this clears the ArrayRef
130 $store->fruit_aisle( [ ] );
136 =item L<Moose::Cookbook::Recipe4> - Subtypes, and modeling a simple Company
139 =item L<Moose::Cookbook::Snack::Types> - Snippets of code for using Types and
142 =item L<Moose::Util::TypeConstraints> - Type constraints that Moose can use
144 =item L<Moose::Autobox> - Autoboxed wrappers for Native Perl datatypes
146 =item L<MooseX::AttributeHelpers> - Extends attribute interfaces
152 Brian Manning <elspicyjack at gmail dot com>
154 =head1 COPYRIGHT AND LICENSE
156 Copyright (c)2008 by Infinity Interactive, Inc., Brian Manning
158 This documentation is free software; you can redistribute it and/or modify
159 it under the same terms as Perl itself.