Rename Basics::Recipe10 to Basics::Person_BUILDARGSAndBUILD
[gitmo/Moose.git] / lib / Moose / Cookbook / Basics / Person_BUILDARGSAndBUILD.pod
CommitLineData
89460279 1package Moose::Cookbook::Basics::Person_BUILDARGSAndBUILD;
c2a0627f 2
daa0fd7d 3# ABSTRACT: Using BUILDARGS and BUILD to hook into object construction
4
5__END__
c2a0627f 6
c2a0627f 7
daa0fd7d 8=pod
c2a0627f 9
10=head1 SYNOPSIS
11
1f476b5f 12 package Person;
c765b254 13
1f476b5f 14 has 'ssn' => (
15 is => 'ro',
16 isa => 'Str',
17 predicate => 'has_ssn',
18 );
c765b254 19
1f476b5f 20 has 'country_of_residence' => (
21 is => 'ro',
22 isa => 'Str',
23 default => 'usa'
24 );
c765b254 25
1f476b5f 26 has 'first_name' => (
27 is => 'ro',
28 isa => 'Str',
29 );
c765b254 30
1f476b5f 31 has 'last_name' => (
32 is => 'ro',
33 isa => 'Str',
34 );
c765b254 35
c30bceb8 36 around BUILDARGS => sub {
37 my $orig = shift;
1f476b5f 38 my $class = shift;
c765b254 39
1f476b5f 40 if ( @_ == 1 && ! ref $_[0] ) {
c30bceb8 41 return $class->$orig(ssn => $_[0]);
1f476b5f 42 }
43 else {
c30bceb8 44 return $class->$orig(@_);
1f476b5f 45 }
c30bceb8 46 };
c2a0627f 47
1f476b5f 48 sub BUILD {
49 my $self = shift;
c765b254 50
1f476b5f 51 if ( $self->country_of_residence eq 'usa' ) {
52 die 'Cannot create a Person who lives in the USA without an ssn.'
53 unless $self->has_ssn;
54 }
c2a0627f 55 }
56
1f476b5f 57=head1 DESCRIPTION
c2a0627f 58
1f476b5f 59This recipe demonstrates the use of C<BUILDARGS> and C<BUILD>. By
60defining these methods, we can hook into the object construction
61process without overriding C<new>.
c765b254 62
1f476b5f 63The C<BUILDARGS> method is called I<before> an object has been
64created. It is called as a class method, and receives all of the
65parameters passed to the C<new> method. It is expected to do something
66with these arguments and return a hash reference. The keys of the hash
67must be attribute C<init_arg>s.
c765b254 68
1f476b5f 69The primary purpose of C<BUILDARGS> is to allow a class to accept
70something other than named arguments. In the case of our C<Person>
71class, we are allowing it to be called with a single argument, a
72social security number:
c765b254 73
1f476b5f 74 my $person = Person->new('123-45-6789');
c765b254 75
1f476b5f 76The key part of our C<BUILDARGS> is this conditional:
c765b254 77
1f476b5f 78 if ( @_ == 1 && ! ref $_[0] ) {
c30bceb8 79 return $class->$orig(ssn => $_[0]);
1f476b5f 80 }
c2a0627f 81
1f476b5f 82By default, Moose constructors accept a list of key-value pairs, or a
83hash reference. We need to make sure that C<$_[0]> is not a reference
84before assuming it is a social security number.
c2a0627f 85
c30bceb8 86We call the original C<BUILDARGS> method to handle all the other
1f476b5f 87cases. You should always do this in your own C<BUILDARGS> methods,
88since L<Moose::Object> provides its own C<BUILDARGS> method that
89handles hash references and a list of key-value pairs.
c2a0627f 90
1f476b5f 91The C<BUILD> method is called I<after> the object is constructed, but
92before it is returned to the caller. The C<BUILD> method provides an
93opportunity to check the object state as a whole. This is a good place
94to put logic that cannot be expressed as a type constraint on a single
95attribute.
c2a0627f 96
1f476b5f 97In the C<Person> class, we need to check the relationship between two
98attributes, C<ssn> and C<country_of_residence>. We throw an exception
99if the object is not logically consistent.
c765b254 100
1f476b5f 101=head1 MORE CONSIDERATIONS
c765b254 102
1f476b5f 103This recipe is made significantly simpler because all of the
104attributes are read-only. If the C<country_of_residence> attribute
105were settable, we would need to check that a Person had an C<ssn> if
106the new country was C<usa>. This could be done with a C<before>
107modifier.
c2a0627f 108
109=head1 CONCLUSION
110
1f476b5f 111We have repeatedly discouraged overriding C<new> in Moose
112classes. This recipe shows how you can use C<BUILDARGS> and C<BUILD>
ad2fbc43 113to hook into object construction without overriding C<new>.
c2a0627f 114
1f476b5f 115The C<BUILDARGS> method lets us expand on Moose's built-in parameter
116handling for constructors. The C<BUILD> method lets us implement
117logical constraints across the whole object after it is created.
c2a0627f 118
1f476b5f 119=cut