=pod =head1 NAME Moose::Cookbook::Snack::HashRef - Using the HashRef type constraint =head1 SYNOPSIS package Fruit; use Moose; has 'species' => ( is => 'rw', required => 1 ); package ProduceStoreHash; use Moose; use Moose::Util::TypeConstraints; has 'fruit_aisle' => ( is => 'rw', isa => 'HashRef[Fruit]' ); package main; use Moose; # we need something to put in the fruit aisle my $orange = Fruit->new( species => 'C. sinensis' ); my $apple = Fruit->new( species => 'M. domestica' ); my %fruit = ( orange => $orange, apple => $apple ); my $store = ProduceStoreHash->new( fruit_aisle => \%fruit ); =head1 DESCRIPTION The HashRef type constraint is used to store a reference to a Perl hash variable as an attribute of a Moose object. =head2 Disclaimer The code in this document will work on Moose as advertised, but the developers strongly recommend using something like L or L when working with hash references in order to help keep your Moose objects nice and encapsulated. =head2 Assigning hashes to a HashRef attribute Once a Moose-based object with a C attribute has been created, you can pass a hash (by reference) to that attribute using that attribute's accessor. This is how we assign the apple and orange to the store's C C attribute, we pass a hash containing both objects by reference to the C attribute: my %fruit = ( orange => $orange, apple => $apple ); my $store = ProduceStoreHash->new( fruit_aisle => \%fruit ); Or you can pass an anonymous hash to the C attribute as well. If you created two new objects, C<$grape> and C<$tomato>, and assigned them to the C, they would replace the apple and the orange in the store's fruit aisle: $store->fruit_aisle( { grape => $grape, tomato => $tomato } ); Our C C example is parameterized, meaning, that the C C can contain nothing but C objects as hash values. If you try to pass in a reference to a hash using C objects as hash values for example, Moose will complain: Attribute (fruit_aisle) does not pass the type constraint (HashRef[Int]) =head2 Dumping the contents of the HashRef In order to dump the contents of a C object attribute, you must first de-reference the C, and then enumerate over it's keys. foreach my $item ( keys(%{$self->fruit_aisle}) ) { my $fruit = $self->{fruit_aisle}{$item}; print "Item: $item, type: " . $fruit->meta->name . " species: " . $fruit->species . "\n"; } If the above de-referencing of the C C is a little too noisy, you could create a copy of it, and then enumerate over that copy: my %fruit_aisle_copy = %{$self->fruit_aisle}; foreach my $item ( keys(%fruit_aisle_copy) ) { my $fruit = $fruit_aisle_copy{$item}; print "Item: $item, type: " . $fruit->meta->name . " species: " . $fruit->species . "\n"; } =head2 Assigning to a HashRef attribute will overwrite Once you create an object containing a C attribute, if you assign a new hash reference to that attribute, it will replace any existing hash reference: # this replaces the existing HashRef contents my $grape = Fruit->new( species => 'V. vinifera' ); my $tomato = Fruit->new( species => 'S. lycopersicum'); $store->fruit_aisle( { grape => $grape, tomato => $tomato } ); =head2 Appending/Deleting key/value pairs to a HashRef In order to append or delete key/value pairs to the hash referred to by the C attribute, you will need to make a copy of the hash first, add or delete the desired key/value pairs, then assign your modified copy back to the C attribute. Here's an example of appending new key/value pars: my %fruit_aisle_copy = %{$store->fruit_aisle}; my $avocado = Fruit->new( species => 'P. americana) ); $fruit_aisle_copy{avocado} = $avocado; $store->fruit_aisle( \%fruit_aisle_copy ); And here's an example of deleting existing key/value pairs: # delete an attribute from the HashRef %fruit_aisle_copy = %{$store->fruit_aisle}; delete($fruit_aisle_copy{tomato}); $store->fruit_aisle( \%fruit_aisle_copy ); Putting the above code into their own object methods would make appending to and deleting from a C a trivial operation. =head2 Clearing the HashRef Assigning C to clear a C will not work because the attribute was originally defined with a type constraint, meaning that attribute must have 0 or more of that type of value to be valid. B in Perl is not a value, so it won't work for clearing the C. If you assign an empty anonymous hash to a C attribute, this will clear out that attribute yet still satisfy the type constraint. # this clears the HashRef $store->fruit_aisle( { } ); =head1 SEE ALSO =over 4 =item L - Snippets of code for using Types and Type Constraints =item L - Type constraints that Moose can use and the tools to extend them or create your own. =item L - Autoboxed wrappers for Native Perl datatypes =item L - Extends attribute interfaces =back =head1 AUTHOR Brian Manning =head1 COPYRIGHT AND LICENSE Copyright 2006-2008 by Infinity Interactive, Inc. L This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut