A few tweaks.
[gitmo/Moose.git] / lib / Moose / Cookbook / Snack / HashRef.pod
CommitLineData
686a7f09 1#!/usr/bin/env perl
2=pod
3
4=head1 NAME
5
6Moose::Cookbook::Snack::HashRef - (Ab)using the HashRef type constraint
7provided by the L<Moose::Util::TypeConstraint> and/or
8L<Moose::Util::TypeConstraints::OptimizedConstraints> classes.
9
10=head1 SYNOPSIS
11
12 package Fruit;
13 use Moose;
14
6bf6edf6 15 has 'species' => ( is => 'rw', required => 1 );
686a7f09 16
17 package ProduceStoreHash;
18 use Moose;
19 use Moose::Util::TypeConstraints;
20
6bf6edf6 21 has 'fruit_aisle' => ( is => 'rw', isa => 'HashRef[Fruit]' );
686a7f09 22
23 package main;
24 use Moose;
25
26 # we need something to put in the fruit aisle
6bf6edf6 27 my $orange = Fruit->new( species => 'C. sinensis' );
28 my $apple = Fruit->new( species => 'M. domestica' );
686a7f09 29 my %fruit = ( orange => $orange, apple => $apple );
30 my $store = ProduceStoreHash->new( fruit_aisle => \%fruit );
686a7f09 31
32=head1 DESCRIPTION
33
34The HashRef type constraint is used to store a reference to a Perl hash
35variable as an attribute of a Moose object.
36
6bf6edf6 37=head2 Disclaimer
38
39The code in this document will work on Moose as advertised, but the developers
40strongly recommend using something like L<Moose::Autobox> or
41L<MooseX::AttributeHelpers> when working with array references in order to
42help keep your Moose objects nice and encapsulated.
43
686a7f09 44=head2 Assigning hashes to a HashRef attribute
45
46Once a Moose-based object with a C<HashRef> attribute has been created, you
47can pass a hash (by reference) to that attribute using that attribute's
48accessor. This is how we assign the apple and orange to the store's
49C<fruit_aisle> C<HashRef> attribute, we pass a hash containing both objects by
50reference to the C<fruit_aisle> attribute:
51
52 my %fruit = ( orange => $orange, apple => $apple );
53 my $store = ProduceStoreHash->new( fruit_aisle => \%fruit );
54
6bf6edf6 55Or you can pass an anonymous hash to the C<HashRef> attribute as well. If you
56created two new objects, C<$grape> and C<$tomato>, and assigned them to the
57C<HashRef>, they would replace the apple and the orange in the store's fruit
58aisle:
686a7f09 59
60 $store->fruit_aisle( { grape => $grape, tomato => $tomato } );
61
62Our C<fruit_aisle> C<HashRef> example is parameterized, meaning, that the
63C<fruit_aisle> C<HashRef> can contain nothing but C<Fruit> objects as hash
64values. If you try to pass in a reference to a hash using C<Int> objects as
65hash 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
71In order to dump the contents of a C<HashRef> object attribute, you must first
72de-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";
686a7f09 78 } # foreach my $item
79
80If the above de-referencing of the C<fruit_aisle> C<HashRef> is a little too
81noisy, 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};
86 # 'print' statement from above example goes here
87 }
88
6bf6edf6 89=head2 Assigning to a HashRef attribute will overwrite
90
91Once you create an object containing a C<HashRef> attribute, if you assign a
92new hash reference to that attribute, it will replace any existing hash
93reference:
94
95 # this replaces the existing HashRef contents
96 my $grape = Fruit->new( species => 'V. vinifera' );
97 my $tomato = Fruit->new( species => 'S. lycopersicum');
98 $store->fruit_aisle( { grape => $grape, tomato => $tomato } );
99
686a7f09 100=head2 Appending/Deleting key/value pairs to a HashRef
101
102In order to append or delete key/value pairs to the hash referred to by the
103C<HashRef> attribute, you will need to make a copy of the hash first, add or
104delete the desired key/value pairs, then assign your modified copy back to the
105C<HashRef> attribute. Here's an example of appending new key/value pars:
106
107 my %fruit_aisle_copy = %{$store->fruit_aisle};
6bf6edf6 108 my $avocado = Fruit->new( species => 'P. americana) );
686a7f09 109 $fruit_aisle_copy{avocado} = $avocado;
110 $store->fruit_aisle( \%fruit_aisle_copy );
111
112And here's an example of deleting existing key/value pairs:
113
114 # delete an attribute from the HashRef
115 %fruit_aisle_copy = %{$store->fruit_aisle};
116 delete($fruit_aisle_copy{tomato});
117 $store->fruit_aisle( \%fruit_aisle_copy );
118
119Putting the above code into their own object methods would make appending to
120and deleting from a C<HashRef> a trivial operation.
121
122=head2 Clearing the HashRef
123
124Assigning C<undef> to clear a C<HashRef> will not work because the attribute
125was originally defined with a type constraint, meaning that attribute must have
1260 or more of that type of value to be valid. B<undef> in Perl is not a value,
127so it won't work for clearing the C<HashRef>.
128
129If you assign an empty anonymous hash to a C<HashRef> attribute, this will
130clear out that attribute yet still satisfy the type constraint.
131
132 # this clears the HashRef
133 $store->fruit_aisle( { } );
134
135=head1 SEE ALSO
136
137=over 4
138
139=item L<Moose::Cookbook::Snack::Types> - Snippets of code for using Types and
140Type Constraints
141
142=item L<Moose::Util::TypeConstraints> - Type constraints system for Moose
143
144=back
145
146=head1 AUTHOR
147
148Brian Manning <elspicyjack at gmail dot com>
149
150=head1 COPYRIGHT AND LICENSE
151
6bf6edf6 152Copyright (c)2008 by Infinity Interactive, Inc., Brian Manning
686a7f09 153
154This documentation is free software; you can redistribute it and/or modify
155it under the same terms as Perl itself.
156
157=cut