X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FCookbook%2FBasics%2FRecipe4.pod;h=d9d5dfdf37a52939d1279ec59ae6f1e05da2dc93;hb=400e15966b814f14c2422b54a081bb8583caf691;hp=6e150f57b1ca3e39731390fb2964765f5b7468d8;hpb=c79239a22fc3b30cac35dec0d704c7da52872aa5;p=gitmo%2FMoose.git diff --git a/lib/Moose/Cookbook/Basics/Recipe4.pod b/lib/Moose/Cookbook/Basics/Recipe4.pod index 6e150f5..d9d5dfd 100644 --- a/lib/Moose/Cookbook/Basics/Recipe4.pod +++ b/lib/Moose/Cookbook/Basics/Recipe4.pod @@ -1,22 +1,20 @@ +package Moose::Cookbook::Basics::Recipe4; -=pod +# ABSTRACT: Subtypes, and modeling a simple B class hierarchy -=begin testing SETUP +__END__ -BEGIN { - eval 'use Regexp::Common; use Locale::US;'; - if ($@) { - diag 'Regexp::Common & Locale::US required for this test'; - ok(1); - exit 0; - } -} -=end testing +=pod + +=begin testing-SETUP -=head1 NAME +use Test::Requires { + 'Locale::US' => '0', + 'Regexp::Common' => '0', +}; -Moose::Cookbook::Basics::Recipe4 - Subtypes, and modeling a simple B class hierarchy +=end testing-SETUP =head1 SYNOPSIS @@ -56,19 +54,15 @@ Moose::Cookbook::Basics::Recipe4 - Subtypes, and modeling a simple B cl sub BUILD { my ( $self, $params ) = @_; - if ( @{ $self->employees || [] } ) { - foreach my $employee ( @{ $self->employees } ) { - $employee->employer($self); - } + foreach my $employee ( @{ $self->employees || [] } ) { + $employee->employer($self); } } after 'employees' => sub { my ( $self, $employees ) = @_; - if ($employees) { - foreach my $employee ( @{$employees} ) { - $employee->employer($self); - } + foreach my $employee ( @{ $employees || [] } ) { + $employee->employer($self); } }; @@ -114,12 +108,12 @@ declaratively create type constraints without building an entire class. In the recipe we also make use of L and L -to build constraints, showing how how constraints can make use of -existing CPAN tools for data validation. +to build constraints, showing how constraints can make use of existing +CPAN tools for data validation. Finally, we introduce the C attribute option. -The the C
class we define two subtypes. The first uses the +In the C
class we define two subtypes. The first uses the L module to check the validity of a state. It accepts either a state abbreviation of full name. @@ -154,10 +148,10 @@ simplifies the code. We don't really need a class for these types, as they're just strings, but we do want to ensure that they're valid. The type constraints we created are reusable. Type constraints are -stored by name in a global registry. This means that we can refer to +stored by name in a global registry, which means that we can refer to them in other classes. Because the registry is global, we do recommend -that you use some sort of pseudo-namespacing in real applications, -like C. +that you use some sort of namespacing in real applications, +like C (just as you would do with class names). These two subtypes allow us to define a simple C
class. @@ -188,7 +182,7 @@ where each element of the array is an C object. It's worth noting that an I array reference also satisfies this constraint. -Parameterizable type constraints (or "container types), such as +Parameterizable type constraints (or "container types"), such as C, can be made more specific with a type parameter. In fact, we can arbitrarily nest these types, producing something like C. However, you can also just use the type by @@ -213,17 +207,15 @@ C attribute: sub BUILD { my ( $self, $params ) = @_; - if ( $self->employees ) { - foreach my $employee ( @{ $self->employees } ) { - $employee->employer($self); - } + foreach my $employee ( @{ $self->employees || [] } ) { + $employee->employer($self); } } -The C method is executed after type constraints are checked, so -it is safe to assume that C<< $self->employees >> will return an array -reference, and that the elements of that array will be C -objects. +The C method is executed after type constraints are checked, so it is +safe to assume that if C<< $self->employees >> has a value, it will be an +array reference, and that the elements of that array reference will be +C objects. We also want to make sure that whenever the C attribute for a C is changed, we also update the C for each @@ -233,18 +225,16 @@ To do this we can use an C modifier: after 'employees' => sub { my ( $self, $employees ) = @_; - if ($employees) { - foreach my $employee ( @{$employees} ) { - $employee->employer($self); - } + foreach my $employee ( @{ $employees || [] } ) { + $employee->employer($self); } }; -Again, as with the C method, we know that the type constraint -check has already happened, so we can just check for definedness on the -C<$employees> argument. +Again, as with the C method, we know that the type constraint check has +already happened, so we know that if C<$employees> is defined it will contain +an array reference of C objects.. -The B class does have demonstrate anything new. It has several +The B class does not really demonstrate anything new. It has several C attributes. It also has a C method, which we first used in L. @@ -262,7 +252,7 @@ arguments to C. Instead, Moose simply passes the same parameters that were passed to the method. A more detailed example of usage can be found in -F. +F. =head1 CONCLUSION @@ -294,28 +284,12 @@ container type, and instead you will have a new type named =item (3) -The C method is actually called by C<< Moose::Object->BUILDALL ->>, which is called by C<< Moose::Object->new >>. The C -method climbs the object inheritance graph and calls any C -methods it finds in the correct order. +The C method is actually called by C<< Moose::Object->new >>. It climbs +the object inheritance graph and calls any C methods it finds in the +correct order. =back -=head1 AUTHORS - -Stevan Little Estevan@iinteractive.comE - -Dave Rolsky Eautarch@urth.orgE - -=head1 COPYRIGHT AND LICENSE - -Copyright 2006-2009 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. - =begin testing { @@ -327,44 +301,49 @@ it under the same terms as Perl itself. use Scalar::Util 'isweak'; my $ii; -lives_ok { - $ii = Company->new( - { - name => 'Infinity Interactive', - address => Address->new( - street => '565 Plandome Rd., Suite 307', - city => 'Manhasset', - state => 'NY', - zip_code => '11030' - ), - employees => [ - Employee->new( - first_name => 'Jeremy', - last_name => 'Shao', - title => 'President / Senior Consultant', - address => - Address->new( city => 'Manhasset', state => 'NY' ) - ), - Employee->new( - first_name => 'Tommy', - last_name => 'Lee', - title => 'Vice President / Senior Developer', - address => - Address->new( city => 'New York', state => 'NY' ) - ), - Employee->new( - first_name => 'Stevan', - middle_initial => 'C', - last_name => 'Little', - title => 'Senior Developer', - address => - Address->new( city => 'Madison', state => 'CT' ) +is( + exception { + $ii = Company->new( + { + name => 'Infinity Interactive', + address => Address->new( + street => '565 Plandome Rd., Suite 307', + city => 'Manhasset', + state => 'NY', + zip_code => '11030' ), - ] - } - ); -} -'... created the entire company successfully'; + employees => [ + Employee->new( + first_name => 'Jeremy', + last_name => 'Shao', + title => 'President / Senior Consultant', + address => Address->new( + city => 'Manhasset', state => 'NY' + ) + ), + Employee->new( + first_name => 'Tommy', + last_name => 'Lee', + title => 'Vice President / Senior Developer', + address => + Address->new( city => 'New York', state => 'NY' ) + ), + Employee->new( + first_name => 'Stevan', + middle_initial => 'C', + last_name => 'Little', + title => 'Senior Developer', + address => + Address->new( city => 'Madison', state => 'CT' ) + ), + ] + } + ); + }, + undef, + '... created the entire company successfully' +); + isa_ok( $ii, 'Company' ); is( $ii->name, 'Infinity Interactive', @@ -472,55 +451,85 @@ foreach my $employee ( @{ $new_company->employees } ) { ## check some error conditions for the subtypes -dies_ok { - Address->new( street => {} ),; -} -'... we die correctly with bad args'; - -dies_ok { - Address->new( city => {} ),; -} -'... we die correctly with bad args'; - -dies_ok { - Address->new( state => 'British Columbia' ),; -} -'... we die correctly with bad args'; - -lives_ok { - Address->new( state => 'Connecticut' ),; -} -'... we live correctly with good args'; - -dies_ok { - Address->new( zip_code => 'AF5J6$' ),; -} -'... we die correctly with bad args'; - -lives_ok { - Address->new( zip_code => '06443' ),; -} -'... we live correctly with good args'; - -dies_ok { - Company->new(),; -} -'... we die correctly without good args'; - -lives_ok { - Company->new( name => 'Foo' ),; -} -'... we live correctly without good args'; - -dies_ok { - Company->new( name => 'Foo', employees => [ Person->new ] ),; -} -'... we die correctly with good args'; - -lives_ok { - Company->new( name => 'Foo', employees => [] ),; -} -'... we live correctly with good args'; +isnt( + exception { + Address->new( street => {} ),; + }, + undef, + '... we die correctly with bad args' +); + +isnt( + exception { + Address->new( city => {} ),; + }, + undef, + '... we die correctly with bad args' +); + +isnt( + exception { + Address->new( state => 'British Columbia' ),; + }, + undef, + '... we die correctly with bad args' +); + +is( + exception { + Address->new( state => 'Connecticut' ),; + }, + undef, + '... we live correctly with good args' +); + +isnt( + exception { + Address->new( zip_code => 'AF5J6$' ),; + }, + undef, + '... we die correctly with bad args' +); + +is( + exception { + Address->new( zip_code => '06443' ),; + }, + undef, + '... we live correctly with good args' +); + +isnt( + exception { + Company->new(),; + }, + undef, + '... we die correctly without good args' +); + +is( + exception { + Company->new( name => 'Foo' ),; + }, + undef, + '... we live correctly without good args' +); + +isnt( + exception { + Company->new( name => 'Foo', employees => [ Person->new ] ),; + }, + undef, + '... we die correctly with good args' +); + +is( + exception { + Company->new( name => 'Foo', employees => [] ),; + }, + undef, + '... we live correctly with good args' +); =end testing