[Moose-commits] r7235 - in Moose/trunk/lib/Moose/Cookbook:
Extending Meta
autarch at code2.0beta.co.uk
autarch at code2.0beta.co.uk
Tue Jan 6 05:38:50 GMT 2009
Author: autarch
Date: 2009-01-05 21:38:50 -0800 (Mon, 05 Jan 2009)
New Revision: 7235
Modified:
Moose/trunk/lib/Moose/Cookbook/Extending/Recipe1.pod
Moose/trunk/lib/Moose/Cookbook/Extending/Recipe2.pod
Moose/trunk/lib/Moose/Cookbook/Meta/Recipe2.pod
Moose/trunk/lib/Moose/Cookbook/Meta/Recipe3.pod
Moose/trunk/lib/Moose/Cookbook/Meta/Recipe4.pod
Moose/trunk/lib/Moose/Cookbook/Meta/Recipe5.pod
Log:
tidy code in pod for consistency
Modified: Moose/trunk/lib/Moose/Cookbook/Extending/Recipe1.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Extending/Recipe1.pod 2009-01-06 05:32:40 UTC (rev 7234)
+++ Moose/trunk/lib/Moose/Cookbook/Extending/Recipe1.pod 2009-01-06 05:38:50 UTC (rev 7235)
@@ -139,10 +139,10 @@
use Moose -traits => [ 'Big', 'Blue' ];
- has 'animal' =>
- ( traits => [ 'Big', 'Blue' ],
- ...
- );
+ has 'animal' => (
+ traits => [ 'Big', 'Blue' ],
+ ...
+ );
If your extension applies to any other metaclass, or the object base
class, you cannot use the trait mechanism.
@@ -185,7 +185,7 @@
Moose::Exporter->setup_import_methods( also => 'Moose' );
sub init_meta {
- shift; # just your package name
+ shift; # just your package name
my %options = @_;
return Moose->init_meta(
@@ -217,13 +217,13 @@
use MooseX::Embiggen::Role::Meta::Class;
use MooseX::Embiggen::Role::Meta::Attribute;
- use MooseX::Embiggen::Role::Meta::Method::Constructor
+ use MooseX::Embiggen::Role::Meta::Method::Constructor;
use MooseX::Embiggen::Role::Object;
Moose::Exporter->setup_import_methods( also => 'Moose' );
sub init_meta {
- shift; # just your package name
+ shift; # just your package name
my %options = @_;
Moose->init_meta(%options);
Modified: Moose/trunk/lib/Moose/Cookbook/Extending/Recipe2.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Extending/Recipe2.pod 2009-01-06 05:32:40 UTC (rev 7234)
+++ Moose/trunk/lib/Moose/Cookbook/Extending/Recipe2.pod 2009-01-06 05:38:50 UTC (rev 7235)
@@ -28,14 +28,13 @@
);
}
-
package MooseX::Debugging::Role::Object;
after 'BUILD' => sub {
my $self = shift;
warn "Made a new " . ref $self . " object\n";
- }
+ };
=head1 DESCRIPTION
Modified: Moose/trunk/lib/Moose/Cookbook/Meta/Recipe2.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Meta/Recipe2.pod 2009-01-06 05:32:40 UTC (rev 7234)
+++ Moose/trunk/lib/Moose/Cookbook/Meta/Recipe2.pod 2009-01-06 05:38:50 UTC (rev 7235)
@@ -7,62 +7,63 @@
=head1 SYNOPSIS
- package MyApp::Meta::Attribute::Labeled;
- use Moose;
- extends 'Moose::Meta::Attribute';
+ package MyApp::Meta::Attribute::Labeled;
+ use Moose;
+ extends 'Moose::Meta::Attribute';
- has label => (
- is => 'rw',
- isa => 'Str',
- predicate => 'has_label',
- );
+ has label => (
+ is => 'rw',
+ isa => 'Str',
+ predicate => 'has_label',
+ );
- package Moose::Meta::Attribute::Custom::Labeled;
- sub register_implementation { 'MyApp::Meta::Attribute::Labeled' }
+ package Moose::Meta::Attribute::Custom::Labeled;
+ sub register_implementation {'MyApp::Meta::Attribute::Labeled'}
- package MyApp::Website;
- use Moose;
- use MyApp::Meta::Attribute::Labeled;
+ package MyApp::Website;
+ use Moose;
+ use MyApp::Meta::Attribute::Labeled;
- has url => (
- metaclass => 'Labeled',
- is => 'rw',
- isa => 'Str',
- label => "The site's URL",
- );
+ has url => (
+ metaclass => 'Labeled',
+ is => 'rw',
+ isa => 'Str',
+ label => "The site's URL",
+ );
- has name => (
- is => 'rw',
- isa => 'Str',
- );
+ has name => (
+ is => 'rw',
+ isa => 'Str',
+ );
- sub dump {
- my $self = shift;
+ sub dump {
+ my $self = shift;
- # iterate over all the attributes in $self
- my %attributes = %{ $self->meta->get_attribute_map };
- while (my ($name, $attribute) = each %attributes) {
+ # iterate over all the attributes in $self
+ my %attributes = %{ $self->meta->get_attribute_map };
+ while ( my ( $name, $attribute ) = each %attributes ) {
- # print the label if available
- if ($attribute->isa('MyApp::Meta::Attribute::Labeled')
- && $attribute->has_label) {
- print $attribute->label;
- }
- # otherwise print the name
- else {
- print $name;
- }
+ # print the label if available
+ if ( $attribute->isa('MyApp::Meta::Attribute::Labeled')
+ && $attribute->has_label ) {
+ print $attribute->label;
+ }
- # print the attribute's value
- my $reader = $attribute->get_read_method;
- print ": " . $self->$reader . "\n";
- }
- }
+ # otherwise print the name
+ else {
+ print $name;
+ }
- package main;
- my $app = MyApp::Website->new(url => "http://google.com", name => "Google");
- $app->dump;
+ # print the attribute's value
+ my $reader = $attribute->get_read_method;
+ print ": " . $self->$reader . "\n";
+ }
+ }
+ package main;
+ my $app = MyApp::Website->new( url => "http://google.com", name => "Google" );
+ $app->dump;
+
=head1 SUMMARY
In this recipe, we begin to really delve into the wonder of meta-programming.
@@ -81,8 +82,8 @@
These objects have methods and (surprisingly) attributes. Let's look at a
concrete example.
- has 'x' => (isa => 'Int', is => 'ro');
- has 'y' => (isa => 'Int', is => 'rw');
+ has 'x' => ( isa => 'Int', is => 'ro' );
+ has 'y' => ( isa => 'Int', is => 'rw' );
Ahh, the veritable x and y of the Point example. Internally, every Point has an
x object and a y object. They have methods (such as "get_value") and attributes
@@ -94,23 +95,23 @@
So you have a C<$point> object, which has C<x> and C<y> methods. How can you
actually access the objects behind these attributes? Here's one way:
- $point->meta->get_attribute_map()
+ $point->meta->get_attribute_map()
C<get_attribute_map> returns a hash reference that maps attribute names to
their objects. In our case, C<get_attribute_map> might return something that
looks like the following:
- {
- x => Moose::Meta::Attribute=HASH(0x196c23c),
- y => Moose::Meta::Attribute=HASH(0x18d1690),
- }
+ {
+ x => Moose::Meta::Attribute=HASH(0x196c23c),
+ y => Moose::Meta::Attribute=HASH(0x18d1690),
+ }
Another way to get a handle on an attribute's object is
C<< $self->meta->get_attribute('name') >>. Here's one thing you can do now that
you can interact with the attribute's object directly:
- print $point->meta->get_attribute('x')->type_constraint;
- => Int
+ print $point->meta->get_attribute('x')->type_constraint;
+ => Int
(As an aside, it's not called C<< ->isa >> because C<< $obj->isa >> is already
taken)
@@ -134,18 +135,18 @@
We get the ball rolling by creating a new attribute metaclass. It starts off
somewhat ungloriously.
- package MyApp::Meta::Attribute::Labeled;
- use Moose;
- extends 'Moose::Meta::Attribute';
+ package MyApp::Meta::Attribute::Labeled;
+ use Moose;
+ extends 'Moose::Meta::Attribute';
You subclass metaclasses the same way you subclass regular classes. (Extra
credit: how in the actual hell can you use the MOP to extend itself?)
- has label => (
- is => 'rw',
- isa => 'Str',
- predicate => 'has_label',
- );
+ has label => (
+ is => 'rw',
+ isa => 'Str',
+ predicate => 'has_label',
+ );
Hey, this looks pretty reasonable! This is plain jane Moose code. Recipe 1
fare. This is merely making a new attribute. An attribute that attributes have.
@@ -156,8 +157,8 @@
C<predicate> is a standard part of C<has>. It just creates a method that asks
the question "Does this attribute have a value?"
- package Moose::Meta::Attribute::Custom::Labeled;
- sub register_implementation { 'MyApp::Meta::Attribute::Labeled' }
+ package Moose::Meta::Attribute::Custom::Labeled;
+ sub register_implementation { 'MyApp::Meta::Attribute::Labeled' }
This lets Moose discover our new metaclass. That way attributes can actually
use it. More on what this is doing in a moment.
@@ -165,19 +166,19 @@
Note that we're done defining the new metaclass! Only nine lines of code, and
not particularly difficult lines, either. Now to start using the metaclass.
- package MyApp::Website;
- use Moose;
- use MyApp::Meta::Attribute::Labeled;
+ package MyApp::Website;
+ use Moose;
+ use MyApp::Meta::Attribute::Labeled;
Nothing new here. We do have to actually load our metaclass to be able to use
it.
- has url => (
- metaclass => 'Labeled',
- is => 'rw',
- isa => 'Str',
- label => "The site's URL",
- );
+ has url => (
+ metaclass => 'Labeled',
+ is => 'rw',
+ isa => 'Str',
+ label => "The site's URL",
+ );
Ah ha! Now we're using the metaclass. We're adding a new attribute, C<url>, to
C<MyApp::Website>. C<has> lets you set the metaclass of the attribute.
@@ -199,35 +200,35 @@
Finally, we see that C<has> is setting our new meta-attribute, C<label>, to
C<"The site's URL">. We can access this meta-attribute with:
- $website->meta->get_attribute('url')->label()
+ $website->meta->get_attribute('url')->label()
Well, back to the code.
- has name => (
- is => 'rw',
- isa => 'Str',
- );
+ has name => (
+ is => 'rw',
+ isa => 'Str',
+ );
Of course, you don't have to use the new metaclass for B<all> new attributes.
Now we begin defining a method that will dump the C<MyApp::Website> instance
for human readers.
- sub dump {
- my $self = shift;
+ sub dump {
+ my $self = shift;
- # iterate over all the attributes in $self
- my %attributes = %{ $self->meta->get_attribute_map };
- while (my ($name, $attribute) = each %attributes) {
+ # iterate over all the attributes in $self
+ my %attributes = %{ $self->meta->get_attribute_map };
+ while ( my ( $name, $attribute ) = each %attributes ) {
Recall that C<get_attribute_map> returns a hashref of attribute names and their
associated objects.
- # print the label if available
- if ($attribute->isa('MyApp::Meta::Attribute::Labeled')
- && $attribute->has_label) {
- print $attribute->label;
- }
+ # print the label if available
+ if ( $attribute->isa('MyApp::Meta::Attribute::Labeled')
+ && $attribute->has_label ) {
+ print $attribute->label;
+ }
We have two checks here. The first is "is this attribute an instance of
C<MyApp::Meta::Attribute::Labeled>?". It's good to code defensively. Even if
@@ -240,18 +241,18 @@
defined in the new metaclass as the "predicate". If we pass both checks, we
print the attribute's label.
- # otherwise print the name
- else {
- print $name;
- }
+ # otherwise print the name
+ else {
+ print $name;
+ }
Another good, defensive coding practice: Provide reasonable defaults.
- # print the attribute's value
- my $reader = $attribute->get_read_method;
- print ": " . $self->$reader . "\n";
- }
- }
+ # print the attribute's value
+ my $reader = $attribute->get_read_method;
+ print ": " . $self->$reader . "\n";
+ }
+ }
Here's another example of using the attribute metaclass.
C<< $attribute->get_read_method >> returns the name of the method that can
@@ -261,9 +262,9 @@
Perl doesn't mind. Another way to write this would be
C<< $self->can($reader)->($self) >>. Yuck. :)
- package main;
- my $app = MyApp::Website->new(url => "http://google.com", name => "Google");
- $app->dump;
+ package main;
+ my $app = MyApp::Website->new( url => "http://google.com", name => "Google" );
+ $app->dump;
And we wrap up the example with a script to show off our newfound magic.
@@ -282,13 +283,13 @@
a metaclass that expires attributes after a certain amount of time. You
might use it as such:
- has site_cache => (
- metaclass => 'TimedExpiry',
- expires_after => { hours => 1 },
- refresh_with => sub { get($_->url) },
- isa => 'Str',
- is => 'ro',
- );
+ has site_cache => (
+ metaclass => 'TimedExpiry',
+ expires_after => { hours => 1 },
+ refresh_with => sub { get( $_->url ) },
+ isa => 'Str',
+ is => 'ro',
+ );
The sky's the limit!
Modified: Moose/trunk/lib/Moose/Cookbook/Meta/Recipe3.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Meta/Recipe3.pod 2009-01-06 05:32:40 UTC (rev 7234)
+++ Moose/trunk/lib/Moose/Cookbook/Meta/Recipe3.pod 2009-01-06 05:38:50 UTC (rev 7235)
@@ -7,61 +7,62 @@
=head1 SYNOPSIS
- package MyApp::Meta::Attribute::Trait::Labeled;
- use Moose::Role;
+ package MyApp::Meta::Attribute::Trait::Labeled;
+ use Moose::Role;
- has label => (
- is => 'rw',
- isa => 'Str',
- predicate => 'has_label',
- );
+ has label => (
+ is => 'rw',
+ isa => 'Str',
+ predicate => 'has_label',
+ );
- package Moose::Meta::Attribute::Custom::Trait::Labeled;
- sub register_implementation { 'MyApp::Meta::Attribute::Trait::Labeled' }
+ package Moose::Meta::Attribute::Custom::Trait::Labeled;
+ sub register_implementation {'MyApp::Meta::Attribute::Trait::Labeled'}
- package MyApp::Website;
- use Moose;
- use MyApp::Meta::Attribute::Trait::Labeled;
+ package MyApp::Website;
+ use Moose;
+ use MyApp::Meta::Attribute::Trait::Labeled;
- has url => (
- traits => [qw/Labeled/],
- is => 'rw',
- isa => 'Str',
- label => "The site's URL",
- );
+ has url => (
+ traits => [qw/Labeled/],
+ is => 'rw',
+ isa => 'Str',
+ label => "The site's URL",
+ );
- has name => (
- is => 'rw',
- isa => 'Str',
- );
+ has name => (
+ is => 'rw',
+ isa => 'Str',
+ );
- sub dump {
- my $self = shift;
+ sub dump {
+ my $self = shift;
- # iterate over all the attributes in $self
- my %attributes = %{ $self->meta->get_attribute_map };
- while (my ($name, $attribute) = each %attributes) {
+ # iterate over all the attributes in $self
+ my %attributes = %{ $self->meta->get_attribute_map };
+ while ( my ( $name, $attribute ) = each %attributes ) {
- # print the label if available
- if ($attribute->does('MyApp::Meta::Attribute::Trait::Labeled')
- && $attribute->has_label) {
- print $attribute->label;
- }
- # otherwise print the name
- else {
- print $name;
- }
+ # print the label if available
+ if ( $attribute->does('MyApp::Meta::Attribute::Trait::Labeled')
+ && $attribute->has_label ) {
+ print $attribute->label;
+ }
- # print the attribute's value
- my $reader = $attribute->get_read_method;
- print ": " . $self->$reader . "\n";
- }
- }
+ # otherwise print the name
+ else {
+ print $name;
+ }
- package main;
- my $app = MyApp::Website->new(url => "http://google.com", name => "Google");
- $app->dump;
+ # print the attribute's value
+ my $reader = $attribute->get_read_method;
+ print ": " . $self->$reader . "\n";
+ }
+ }
+ package main;
+ my $app = MyApp::Website->new( url => "http://google.com", name => "Google" );
+ $app->dump;
+
=head1 BUT FIRST
This recipe is a continuation of
@@ -110,22 +111,22 @@
indicate that defining and using a trait is very similar to defining and using
a new attribute metaclass.
- package MyApp::Meta::Attribute::Trait::Labeled;
- use Moose::Role;
+ package MyApp::Meta::Attribute::Trait::Labeled;
+ use Moose::Role;
- has label => (
- is => 'rw',
- isa => 'Str',
- predicate => 'has_label',
- );
+ has label => (
+ is => 'rw',
+ isa => 'Str',
+ predicate => 'has_label',
+ );
Instead of subclassing L<Moose::Meta::Attribute>, we define a role. Traits
don't need any special methods or attributes. You just focus on whatever it is
you actually need to get done. Here we're adding a new meta-attribute for use
in our application.
- package Moose::Meta::Attribute::Custom::Trait::Labeled;
- sub register_implementation { 'MyApp::Meta::Attribute::Trait::Labeled' }
+ package Moose::Meta::Attribute::Custom::Trait::Labeled;
+ sub register_implementation { 'MyApp::Meta::Attribute::Trait::Labeled' }
Much like when we define a new attribute metaclass, we can provide a shorthand
name for the trait. Moose looks at the C<register_implementation> method in
@@ -135,22 +136,22 @@
Now we begin writing our application logic. I'll only cover what has changed
since recipe 2.
- has url => (
- traits => [qw/Labeled/],
- is => 'rw',
- isa => 'Str',
- label => "The site's URL",
- );
+ has url => (
+ traits => [qw/Labeled/],
+ is => 'rw',
+ isa => 'Str',
+ label => "The site's URL",
+ );
L<Moose/has> provides a C<traits> option. Just pass the list of trait names and
it will compose them together to form the (anonymous) attribute metaclass used
by the attribute. We provide a label for the attribute in the same way.
- # print the label if available
- if ($attribute->does('MyApp::Meta::Attribute::Trait::Labeled')
- && $attribute->has_label) {
- print $attribute->label;
- }
+ # print the label if available
+ if ( $attribute->does('MyApp::Meta::Attribute::Trait::Labeled')
+ && $attribute->has_label ) {
+ print $attribute->label;
+ }
Previously, this code asked the question "Does this attribute use our attribute
metaclass?" Since we're now using a trait, we ask "Does this attribute's
@@ -169,13 +170,13 @@
easily get a regular metaclass extension out of it. You just compose the trait
in the attribute metaclass, as normal.
- package MyApp::Meta::Attribute::Labeled;
- use Moose;
- extends 'Moose::Meta::Attribute';
- with 'MyApp::Meta::Attribute::Trait::Labeled';
+ package MyApp::Meta::Attribute::Labeled;
+ use Moose;
+ extends 'Moose::Meta::Attribute';
+ with 'MyApp::Meta::Attribute::Trait::Labeled';
- package Moose::Meta::Attribute::Custom::Labeled;
- sub register_implementation { 'MyApp::Meta::Attribute::Labeled' }
+ package Moose::Meta::Attribute::Custom::Labeled;
+ sub register_implementation { 'MyApp::Meta::Attribute::Labeled' }
Unfortunately, going the other way (providing a trait created from a metaclass)
is more tricky. Thus, defining your extensions as traits is just plain better
Modified: Moose/trunk/lib/Moose/Cookbook/Meta/Recipe4.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Meta/Recipe4.pod 2009-01-06 05:32:40 UTC (rev 7234)
+++ Moose/trunk/lib/Moose/Cookbook/Meta/Recipe4.pod 2009-01-06 05:38:50 UTC (rev 7235)
@@ -11,10 +11,10 @@
use Moose;
extends 'Moose::Meta::Class';
- has table =>
- ( is => 'rw',
- isa => 'Str',
- );
+ has table => (
+ is => 'rw',
+ isa => 'Str',
+ );
=head1 DESCRIPTION
@@ -38,7 +38,7 @@
Using this new "table" attribute is quite simple. Let's say we have a
class named C<MyApp::User>, we could simply write the following:
- my $table = MyApp::User->meta()->table();
+ my $table = MyApp::User->meta->table;
As long as MyApp::User has arranged to use C<MyApp::Meta::Class> as
its metaclass, this method call just works.
Modified: Moose/trunk/lib/Moose/Cookbook/Meta/Recipe5.pod
===================================================================
--- Moose/trunk/lib/Moose/Cookbook/Meta/Recipe5.pod 2009-01-06 05:32:40 UTC (rev 7234)
+++ Moose/trunk/lib/Moose/Cookbook/Meta/Recipe5.pod 2009-01-06 05:38:50 UTC (rev 7235)
@@ -10,10 +10,10 @@
package MyApp::Meta::Class::Trait::HasTable;
use Moose::Role;
- has table =>
- ( is => 'rw',
- isa => 'Str',
- );
+ has table => (
+ is => 'rw',
+ isa => 'Str',
+ );
package Moose::Meta::Class::Custom::Trait::HasTable;
sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' }
@@ -42,7 +42,7 @@
Once this trait has been applied to a metaclass, it looks exactly like
the example we saw in L<Moose::Cookbook::Meta::Recipe4>:
- my $table = MyApp::User->meta()->table();
+ my $table = MyApp::User->meta->table;
=head1 SEE ALSO
More information about the Moose-commits
mailing list