From: Shawn M Moore Date: Sun, 10 May 2009 16:30:51 +0000 (-0400) Subject: Expand tutorial a bit more X-Git-Tag: 0.06~7 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=f2ef35470724da19827b1db7774f2616d199ff2d;p=gitmo%2FMooseX-Role-Parameterized.git Expand tutorial a bit more --- diff --git a/lib/MooseX/Role/Parameterized/Tutorial.pod b/lib/MooseX/Role/Parameterized/Tutorial.pod index 5aba03b..1bfe955 100644 --- a/lib/MooseX/Role/Parameterized/Tutorial.pod +++ b/lib/MooseX/Role/Parameterized/Tutorial.pod @@ -1,7 +1,4 @@ -package MooseX::Role::Parameterized::Tutorial; -confess "Don't use this module, read it!"; - -__END__ +=pod =head1 NAME @@ -10,20 +7,20 @@ MooseX::Role::Parameterized::Tutorial - why and how =head1 MOTIVATION Roles are composable units of behavior. They are useful for factoring out -functionality common to many classes from any part of your class hierarchy.See +functionality common to many classes from any part of your class hierarchy. See L for an introduction to L. While combining roles affords you a great deal of flexibility, individual roles -have very little in the way of configurability. Core Moose provides C -for renaming methods to avoid conflicts, and C for ignoring methods -you don't want or need (see L for more -about C and C). +have very little in the way of configurability. Core Moose provides C +for renaming methods and C for ignoring methods. These options are +primarily (perhaps solely) for disambiguating role conflicts. See +L for more about C and C. Because roles serve many different masters, they usually provide only the least common denominator of functionality. To empower roles further, more configurability than C and C is required. Perhaps your role needs to know which method to call when it is done. Or what default value to -use for its url attribute. +use for its C attribute. Parameterized roles offer exactly this solution. @@ -40,6 +37,16 @@ C to ordinary roles: log_to => 'query.log', }; +You can still combine parameterized roles. You just need to specify parameters +immediately after the role they belong to: + + with ( + 'My::Parameterized::Role' => { + needs_better_example => 1, + }, + 'My::Other::Role', + ); + =head3 C Inside your parameterized role, you specify a set of parameters. This is @@ -51,22 +58,20 @@ the keyword C, but your parameters can use any options to C. predicate => 'has_delegation', ); -Behind the scenes, C uses C to add attributes to a parameter -class (except the "is" option defaults to "ro" for convenience). The arguments -to C are used to construct a parameter object, which has the attributes -specified by calls to C. The parameter object is then passed to... +You do have to declare what parameters you accept, just like you have to +declare what attributes you accept for regular Moose objects. =head3 C C takes a block of code that will be used to generate your role with its parameters bound. Here is where you declare parameterized components: use -C, method modifiers, and so on. You receive as an argument the parameter -object constructed by C. You can access the parameters just like regular -attributes on that object (assuming you declared them readable). +C, method modifiers, and so on. The C block receives an argument, +which contains the parameters specified by C. You can access the +parameters just like regular attributes on that object. Each time you compose this parameterized role, the role {} block will be executed. It will receive a new parameter object and produce an entirely new -role. +role. That's the whole point, after all. Due to limitations inherent in Perl, you must declare methods with C<< method name => sub { ... } >> instead of the usual C. @@ -92,11 +97,21 @@ can now also choose type, default value, whether it's required, B, etc. default => sub { [] }, ); - has action => ( - traits => $p->traits, - ... + parameter type => ( + isa => 'Str', + default => 'Any', ); + role { + my $p = shift; + + has action => ( + traits => $p->traits, + isa => $p->type, + ... + ); + } + =item Inform a role of your class' attributes and methods Core roles can require only methods with specific names. Now your roles can @@ -108,7 +123,10 @@ which attributes to dump to a file. required => 1, ); - around $p->instrument_method => sub { ... }; + role { + my $p = shift; + around $p->instrument_method => sub { ... }; + } =item Arbitrary execution choices @@ -121,11 +139,14 @@ states. default => 0, ); - method process => sub { - ... - if ($p->save_intermediate) { ... } - ... - }; + role { + my $p = shift; + method process => sub { + ... + if ($p->save_intermediate) { ... } + ... + }; + } =item Deciding a backend @@ -137,12 +158,18 @@ L. Which backend to use can be a parameter. default => 'Storable', ); - if ($p->format eq 'Storable') { - method freeze => sub { ... }; - method thaw => sub { ... }; + role { + my $p = shift; + if ($p->format eq 'Storable') { + method freeze => \&Storable::freeze; + method thaw => \&Storable::thaw; + } + elsif ($p->format eq 'YAML') { + method freeze => \&YAML::Dump; + method thaw => \&YAML::Load; + } + ... } - elsif ($p->format eq 'YAML') ... - ... =back