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