Commit | Line | Data |
3a0c064a |
1 | |
686a7f09 |
2 | =pod |
3 | |
4 | =head1 NAME |
5 | |
3a0c064a |
6 | Moose::Cookbook::Snack::ArrayRef - Using the ArrayRef type constraint |
686a7f09 |
7 | |
8 | =head1 SYNOPSIS |
9 | |
10 | package Fruit; |
11 | use Moose; |
12 | |
6bf6edf6 |
13 | has 'name' => (is => 'rw', required => 1); |
14 | has 'species' => (is => 'rw', required => 1); |
686a7f09 |
15 | |
16 | package ProduceStoreArray; |
17 | use Moose; |
18 | use Moose::Util::TypeConstraints; |
19 | |
6bf6edf6 |
20 | has 'fruit_aisle' => (isa => 'ArrayRef[Fruit]', is => 'rw'); |
686a7f09 |
21 | |
22 | package main; |
23 | |
24 | # we need something to put in the fruit aisle |
6bf6edf6 |
25 | my $orange = Fruit->new(name => 'orange', species => 'C. sinensis'); |
26 | my $apple = Fruit->new(name => 'apple', species => 'M. domestica'); |
27 | my @fruit = ($apple, $orange); |
fbde43ee |
28 | my $store = ProduceStoreArray->new(fruit_aisle => \@fruit); |
686a7f09 |
29 | |
30 | =head1 DESCRIPTION |
31 | |
32 | The ArrayRef type constraint is used to store a reference to a Perl list or |
33 | array variable as an attribute of a Moose object. |
34 | |
6bf6edf6 |
35 | =head2 Disclaimer |
36 | |
37 | The code in this document will work on Moose as advertised, but the developers |
38 | strongly recommend using something like L<Moose::Autobox> or |
39 | L<MooseX::AttributeHelpers> when working with array references in order to |
40 | help keep your Moose objects nice and encapsulated. |
41 | |
686a7f09 |
42 | =head2 Assigning arrays to an ArrayRef attribute |
43 | |
44 | Once a Moose-based object with an C<ArrayRef> attribute has been created, you |
45 | can pass an array (by reference) to that object attribute using that |
46 | attribute's accessor. This is how we assign the apple and orange to the |
47 | store's C<fruit_aisle> C<ArrayRef> attribute, we pass an array containing both |
48 | objects by reference to the C<fruit_aisle> attribute: |
49 | |
6bf6edf6 |
50 | my @fruit = ($apple, $orange); |
fbde43ee |
51 | my $store = ProduceStoreArray->new(fruit_aisle => \@fruit); |
686a7f09 |
52 | |
6bf6edf6 |
53 | Or you can pass an anonymous array to the C<ArrayRef> attribute as well. If |
54 | you created two new objects, C<$grape> and C<$tomato>, and assigned them to |
55 | the C<ArrayRef>, they would replace the apple and the orange in the store's |
56 | fruit aisle: |
686a7f09 |
57 | |
6bf6edf6 |
58 | $store->fruit_aisle( [$grape, $tomato] ); |
686a7f09 |
59 | |
60 | Our C<fruit_aisle> C<ArrayRef> is parameterized, meaning, that the |
61 | C<fruit_aisle> C<ArrayRef> can contain nothing but C<Fruit> objects as array |
62 | values. If you try to pass in a reference to a array using C<Str> objects as |
63 | array values for example, Moose will complain: |
64 | |
65 | Attribute (fruit_aisle) does not pass the type constraint (ArrayRef[Str]) |
66 | |
67 | =head2 Dumping the contents of an ArrayRef |
68 | |
69 | In order to dump the contents of a C<ArrayRef> object attribute, you must first |
70 | de-reference the C<ArrayRef>, and then enumerate over it's keys. You can add |
71 | this method for showing the store's inventory to the C<ProduceStoreArray> |
72 | object shown in the SYNOPSIS: |
73 | |
74 | sub show_inventory { |
75 | my $self = shift; |
76 | foreach my $item ( @{$self->fruit_aisle} ) { |
3a0c064a |
77 | # ... access each Fruit object |
78 | } |
686a7f09 |
79 | } |
80 | |
81 | =head2 Assigning arrays to an ArrayRef will overwrite existing arrays |
82 | |
83 | Once you create an object containing a C<ArrayRef> attribute, if you assign a |
84 | new array reference to that attribute, it will replace any existing array |
85 | reference: |
86 | |
87 | # replace existing inventory |
6bf6edf6 |
88 | my $grape = Fruit->new(name => 'grape', species => 'V. vinifera'); |
89 | my $tomato = Fruit->new(name => 'tomato', species => 'S. lycopersicum'); |
90 | $store->fruit_aisle( [$grape, $tomato] ); |
686a7f09 |
91 | |
92 | =head2 Appending/Deleting values to/from an ArrayRef |
93 | |
94 | In order to append new elements to an array referred to by the C<ArrayRef> |
95 | attribute, you will need to make a copy of the array first, add your new array |
96 | elements, then assign your modified copy back to the C<ArrayRef> attribute: |
97 | |
98 | my @fruit_aisle_copy = @{$store->fruit_aisle}; |
6bf6edf6 |
99 | my $avocado = Fruit->new(name => 'avocado', species => 'P. americana'); |
686a7f09 |
100 | push(@fruit_aisle_copy, $avocado); |
101 | $store->fruit_aisle( \@fruit_aisle_copy ); |
102 | |
103 | And here's an example of deleting an object stored in an ArrayRef: |
104 | |
105 | my @fruit_aisle_copy = @{$store->fruit_aisle}; |
106 | # new array to hold the fruit objects that won't be deleted |
107 | my @reworked_fruit_aisle; |
108 | for my $fruit_obj ( @fruit_aisle_copy ) { |
6bf6edf6 |
109 | if ( $fruit_obj->name ne 'tomato' ) { |
686a7f09 |
110 | push(@reworked_fruit_aisle, $fruit_obj); |
3a0c064a |
111 | } |
112 | } |
686a7f09 |
113 | $store->fruit_aisle( \@reworked_fruit_aisle ); |
114 | |
115 | Putting the above code into their own object methods would make appending to or deleting from an C<ArrayRef> a trivial operation. |
116 | |
117 | =head2 Clearing an ArrayRef |
118 | |
119 | Assigning C<undef> to clear an C<ArrayRef> will not work because the attribute |
120 | was originally defined with a type constraint, meaning that attribute must have |
121 | 0 or more of that type of value to be valid. C<undef> in Perl is not a value, |
122 | so it won't work for clearing the C<ArrayRef>. |
123 | |
124 | If you assign an empty anonymous hash to a C<ArrayRef> attribute, this will |
125 | clear out that attribute yet still satisfy the type constraint. |
126 | |
127 | # this clears the ArrayRef |
128 | $store->fruit_aisle( [ ] ); |
129 | |
130 | =head1 SEE ALSO |
131 | |
132 | =over 4 |
133 | |
134 | =item L<Moose::Cookbook::Recipe4> - Subtypes, and modeling a simple Company |
135 | class hierarchy |
136 | |
137 | =item L<Moose::Cookbook::Snack::Types> - Snippets of code for using Types and |
138 | Type Constraints |
139 | |
140 | =item L<Moose::Util::TypeConstraints> - Type constraints that Moose can use |
3a0c064a |
141 | and the tools to extend them or create your own. |
686a7f09 |
142 | |
6bf6edf6 |
143 | =item L<Moose::Autobox> - Autoboxed wrappers for Native Perl datatypes |
144 | |
145 | =item L<MooseX::AttributeHelpers> - Extends attribute interfaces |
146 | |
686a7f09 |
147 | =back |
148 | |
149 | =head1 AUTHOR |
150 | |
151 | Brian Manning <elspicyjack at gmail dot com> |
152 | |
153 | =head1 COPYRIGHT AND LICENSE |
154 | |
3a0c064a |
155 | Copyright 2006-2008 by Infinity Interactive, Inc. |
156 | |
157 | L<http://www.iinteractive.com> |
686a7f09 |
158 | |
3a0c064a |
159 | This library is free software; you can redistribute it and/or modify |
686a7f09 |
160 | it under the same terms as Perl itself. |
161 | |
162 | =cut |