From: Stevan Little Date: Tue, 28 Mar 2006 17:42:28 +0000 (+0000) Subject: cleanup X-Git-Tag: 0_05~54 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=172e0738bcc43e24a71b4e344f8ce2cd8a7d1852;p=gitmo%2FMoose.git cleanup --- diff --git a/lib/Moose/Cookbook/Recipe4.pod b/lib/Moose/Cookbook/Recipe4.pod index b4f38ed..26265a5 100644 --- a/lib/Moose/Cookbook/Recipe4.pod +++ b/lib/Moose/Cookbook/Recipe4.pod @@ -20,7 +20,8 @@ Moose::Cookbook::Recipe4 subtype USState => as Str => where { - (exists $STATES->{code2state}{uc($_)} || exists $STATES->{state2code}{uc($_)}) + (exists $STATES->{code2state}{uc($_)} || + exists $STATES->{state2code}{uc($_)}) }; subtype USZipCode @@ -63,13 +64,17 @@ Moose::Cookbook::Recipe4 has 'first_name' => (is => 'rw', isa => 'Str', required => 1); has 'last_name' => (is => 'rw', isa => 'Str', required => 1); - has 'middle_initial' => (is => 'rw', isa => 'Str', predicate => 'has_middle_initial'); + has 'middle_initial' => (is => 'rw', isa => 'Str', + predicate => 'has_middle_initial'); has 'address' => (is => 'rw', isa => 'Address'); sub full_name { my $self = shift; return $self->first_name . - ($self->has_middle_initial ? ' ' . $self->middle_initial . '. ' : ' ') . + ($self->has_middle_initial ? + ' ' . $self->middle_initial . '. ' + : + ' ') . $self->last_name; } @@ -90,6 +95,91 @@ Moose::Cookbook::Recipe4 =head1 DESCRIPTION +In this recipe we introduce the C keyword, and show +how that can be useful for specifying specific type constraints +without having to build an entire class to represent them. We +will also show how this feature can be used to leverage the +usefulness of CPAN modules. In addition to this, we will also +introduce another attribute option as well. + +Lets first get into the C features. In the B
+class we have defined two subtypes. The first C uses +the L module, which provides two hashes which can be +used to do existence checks for state names and their two letter +state codes. It is a very simple, and very useful module, and +perfect to use in a C constraint. + + my $STATES = Locale::US->new; + subtype USState + => as Str + => where { + (exists $STATES->{code2state}{uc($_)} || + exists $STATES->{state2code}{uc($_)}) + }; + +Because we know that states will be passed to us as strings, we +can make C a subtype of the built-in type constraint +C. This will assure that anything which is a C will +also pass as a C. Next, we create a constraint specializer +using the C keyword. The value being checked against in +the C clause can be found in the C<$_> variable (1). Our +constraint specializer will then look to see if the string given +is either a state name or a state code. If the string meets this +criteria, then the constraint will pass, otherwise it will fail. +We can now use this as we would any built-in constraint, like so: + + has 'state' => (is => 'rw', isa => 'USState'); + +The C accessor will now check all values against the +C constraint, thereby only allowing valid state names or +state codes to be stored in the C slot. + +The next C, does pretty much the same thing using the +L module, and constrainting the C slot. + + subtype USZipCode + => as Value + => where { + /^$RE{zip}{US}{-extended => 'allow'}$/ + }; + +Using subtypes can save a lot of un-needed abstraction by not +requiring you to create many small classes for these relatively +simple values. It also allows you to define these constraints +and share them among many different classes (avoiding unneeded +duplication) because type constraints are stored by string in a +global registry and always accessible to C. + +With these two subtypes and some attributes, we pretty much define +as much as we need for a basic B
class. Next we define +a basic B class, which itself has an address. As we saw in +earlier recipes, we can use the C
type constraint that +Moose automatically created for us. + + has 'address' => (is => 'rw', isa => 'Address'); + +A company also needs a name, so we define that too. + + has 'name' => (is => 'rw', isa => 'Str', required => 1); + +Here we introduce another attribute option, the C option. +This option tells Moose that C is a required parameter in +the B constructor, and that the C accessor cannot +accept an undefined value for the slot. The result is that C +should always have a value. + +=head1 FOOTNOTES + +=over 4 + +=item (1) + +The value being checked is also passed as the first argument to +the C block as well, so it can also be accessed as C<$_[0]> +as well. + +=back + =head1 AUTHOR Stevan Little Estevan@iinteractive.comE