Redid the augment exercises and based it on a non-XML
Dave Rolsky [Thu, 25 Jun 2009 16:54:45 +0000 (11:54 -0500)]
TPSReport. Hopefully this will be a little simpler to grok.

moose-class/exercises/answers/04-method-modifiers/Document.pm [new file with mode: 0644]
moose-class/exercises/answers/04-method-modifiers/Employee.pm
moose-class/exercises/answers/04-method-modifiers/OutputsXML.pm [deleted file]
moose-class/exercises/answers/04-method-modifiers/Person.pm
moose-class/exercises/answers/04-method-modifiers/Report.pm [new file with mode: 0644]
moose-class/exercises/answers/04-method-modifiers/TPSReport.pm [new file with mode: 0644]
moose-class/exercises/t/04-method-modifiers.t
moose-class/exercises/t/lib/MooseClass/Tests.pm

diff --git a/moose-class/exercises/answers/04-method-modifiers/Document.pm b/moose-class/exercises/answers/04-method-modifiers/Document.pm
new file mode 100644 (file)
index 0000000..c44d165
--- /dev/null
@@ -0,0 +1,28 @@
+package Document;
+
+use Moose;
+
+has [ qw( title author ) ] => ( is => 'ro' );
+
+sub output {
+    my $self = shift;
+
+    my $t = $self->title;
+    my $a = $self->author;
+
+    my $content = inner();
+
+    return <<"EOF";
+$t
+
+$content
+
+Written by $a
+EOF
+}
+
+no Moose;
+
+__PACKAGE__->meta->make_immutable;
+
+1;
index 1bb91fd..11b8db4 100644 (file)
@@ -28,14 +28,6 @@ sub _build_salary {
     return $self->salary_level * 10000;
 }
 
-augment as_xml => sub {
-    my $self = shift;
-
-    return
-        ( map { "<$_>" . ( $self->$_ || q{} ) . "</$_>" } qw( salary salary_level ssn ) ),
-        inner();
-};
-
 no Moose;
 
 __PACKAGE__->meta->make_immutable;
diff --git a/moose-class/exercises/answers/04-method-modifiers/OutputsXML.pm b/moose-class/exercises/answers/04-method-modifiers/OutputsXML.pm
deleted file mode 100644 (file)
index db30970..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-package OutputsXML;
-
-use Moose::Role;
-
-requires 'as_xml';
-
-around as_xml => sub {
-    my $orig = shift;
-    my $self = shift;
-
-    return
-          qq{<?xml version="1.0" encoding="UTF-8"?>\n} . q{<}
-        . ( ref $self ) . q{>} . "\n"
-        . ( join "\n", $self->$orig(@_) ) . "\n" . q{</}
-        . ( ref $self ) . q{>} . "\n";
-};
-
-no Moose::Role;
-
-1;
index e1edc60..6c4ce19 100644 (file)
@@ -26,14 +26,6 @@ sub full_name {
 
 sub as_string { $_[0]->full_name }
 
-sub as_xml {
-    my $self = shift;
-
-    return
-        ( map { "<$_>" . ( $self->$_ || q{} ) . "</$_>" } qw( first_name last_name title ) ),
-        inner();
-}
-
 no Moose;
 
 __PACKAGE__->meta->make_immutable;
diff --git a/moose-class/exercises/answers/04-method-modifiers/Report.pm b/moose-class/exercises/answers/04-method-modifiers/Report.pm
new file mode 100644 (file)
index 0000000..723ab75
--- /dev/null
@@ -0,0 +1,27 @@
+package Report;
+
+use Moose;
+
+extends 'Document';
+
+has 'summary' => ( is => 'ro' );
+
+augment output => sub {
+    my $self = shift;
+
+    my $content = inner();
+
+    my $s = $self->summary;
+
+    return <<"EOF";
+$s
+
+$content
+EOF
+};
+
+no Moose;
+
+__PACKAGE__->meta->make_immutable;
+
+1;
diff --git a/moose-class/exercises/answers/04-method-modifiers/TPSReport.pm b/moose-class/exercises/answers/04-method-modifiers/TPSReport.pm
new file mode 100644 (file)
index 0000000..c88a79a
--- /dev/null
@@ -0,0 +1,19 @@
+package TPSReport;
+
+use Moose;
+
+extends 'Report';
+
+has [ qw( t p s ) ] => ( is => 'ro' );
+
+augment output => sub {
+    my $self = shift;
+
+    return join q{}, map { "$_: " . $self->$_ . "\n" } qw( t p s );
+};
+
+no Moose;
+
+__PACKAGE__->meta->make_immutable;
+
+1;
index 8cf97ae..193b6c0 100644 (file)
@@ -1,41 +1,43 @@
 # Your tasks ...
 #
-# You are going to make our Person and Employee classes capable of
-# outputting an XML document describing the object.
+# First, we will create a set of three new classes to make use of the
+# augment method modifier. The class hierarchy will look like this:
 #
-# The document will contain a tag and value for each attribute.
+#   Document
+#      |
+#   Report
+#      |
+#   TPSReport
 #
-# You will use method modifiers and roles to achieve this.
+# The Document class should have two read-only attributes: "title" and
+# "author".
 #
-# Start by creating a new role, OutputsXML.
+# The Report class should have one read-only attributes: "summary".
 #
-# This role should require an "as_xml" method in the classes which
-# consume it.
+# Finally, the TPSReport class should have three read-only attributes:
+# "t", "p", and "s".
 #
-# This role should also use an around modifier on the as_xml method in
-# order to make sure the document is well-formed XML.
+# The goal is to produce a report that looks this:
 #
-# This document will look something like this:
+# $title
 #
-# <?xml version="1.0" encoding="UTF-8"?>
-# <Person>
-# <first_name>Joe</first_name>
-# <last_name>Smith</last_name>
-# </Person>
+# $summary
 #
-# Use the role to create the xml declaration (the first line) and the
-# container tags (<person> or <employee>)
+# t: $t
+# p: $p
+# s: $s
 #
-# The classes should return a list strings. Each string should be a
-# tagged value for an attribute. For consistency, return the
-# attributes in sorted order.
+# Written by $author
 #
-# ( '<first_name>Joe</first_name>', '<last_name>Smith</last_name>' )
+# This report will be a string returned by the Document->output
+# method.
 #
-# If an attribute is empty, just output an empty tag (<foo></foo>).
+# Don't worry too much about how many newlines separate each item (as
+# long as it's at least one). The test does a little massaging to make
+# this more forgiving.
 #
-# Use an augment modifier in the Person and Employee classes to allow
-# Employee to return just its own attributes.
+# Use augment method modifiers in Report and TPSReport to "inject" the
+# relevant content, while Document will output the $title and $author.
 
 use strict;
 use warnings;
@@ -44,7 +46,6 @@ use lib 't/lib';
 
 use MooseClass::Tests;
 
-use Person;
-use Employee;
+use TPSReport;
 
 MooseClass::Tests::tests04();
index d72a92b..11b98d4 100644 (file)
@@ -109,19 +109,43 @@ sub tests04 {
     {
         local $Test::Builder::Level = $Test::Builder::Level + 1;
 
-        no_droppings('OutputsXML');
+        has_meta('Document');
+        has_meta('Report');
+        has_meta('TPSReport');
 
-        does_role( 'Person', 'OutputsXML' );
+        no_droppings('Document');
+        no_droppings('Report');
+        no_droppings('TPSReport');
+
+        has_ro_attr( 'Document',  $_ ) for qw( title author );
+        has_ro_attr( 'Report',    'summary' );
+        has_ro_attr( 'TPSReport', $_ ) for qw( t p s );
+
+        has_method( 'Document', 'output' );
+        has_augmented_method( 'Report', 'output' );
+        has_augmented_method( 'TPSReport', 'output' );
     }
 
-    ok( scalar OutputsXML->meta->get_around_method_modifiers('as_xml'),
-        'OutputsXML has an around modifier for as_xml' );
+    my $tps = TPSReport->new(
+        title   => 'That TPS Report',
+        author  => 'Peter Gibbons (for Bill Lumberg)',
+        summary => 'I celebrate his whole collection!',
+        t       => 'PC Load Letter',
+        p       => 'Swingline',
+        s       => 'flair!',
+    );
 
-    isa_ok( Employee->meta->get_method('as_xml'),
-            'Moose::Meta::Method::Augmented', 'as_xml is augmented in Employee' );
+    my $output = $tps->output;
+    $output =~ s/\n\n+/\n/g;
 
-    person04();
-    employee04();
+    is( $output, <<'EOF', 'output returns expected report' );
+That TPS Report
+I celebrate his whole collection!
+t: PC Load Letter
+p: Swingline
+s: flair!
+Written by Peter Gibbons (for Bill Lumberg)
+EOF
 }
 
 sub tests06 {
@@ -238,6 +262,17 @@ sub has_overridden_method {
     isa_ok( $meth, 'Moose::Meta::Method::Overridden' );
 }
 
+sub has_augmented_method {
+    my $class = shift;
+    my $name  = shift;
+
+    my $articled = A($name);
+    ok( $class->meta->has_method($name), "$class has $articled method" );
+
+    my $meth = $class->meta->get_method($name);
+    isa_ok( $meth, 'Moose::Meta::Method::Augmented' );
+}
+
 sub no_droppings {
     my $class = shift;
 
@@ -360,48 +395,6 @@ sub employee03 {
         'salary is calculated from salary_level, and salary passed to constructor is ignored' );
 }
 
-
-sub person04 {
-    my $person = Person->new(
-        first_name => 'Bilbo',
-        last_name  => 'Baggins',
-    );
-
-    my $xml = <<'EOF';
-<?xml version="1.0" encoding="UTF-8"?>
-<Person>
-<first_name>Bilbo</first_name>
-<last_name>Baggins</last_name>
-<title></title>
-</Person>
-EOF
-
-    is( $person->as_xml, $xml, 'Person outputs expected XML' );
-}
-
-sub employee04 {
-    my $employee = Employee->new(
-        first_name   => 'Jimmy',
-        last_name    => 'Foo',
-        ssn          => '123-99-4567',
-        salary_level => 3,
-    );
-
-    my $xml = <<'EOF';
-<?xml version="1.0" encoding="UTF-8"?>
-<Employee>
-<first_name>Jimmy</first_name>
-<last_name>Foo</last_name>
-<title>Worker</title>
-<salary>30000</salary>
-<salary_level>3</salary_level>
-<ssn>123-99-4567</ssn>
-</Employee>
-EOF
-
-    is( $employee->as_xml, $xml, 'Employee outputs expected XML' );
-}
-
 sub person06 {
     my $person = Person->new(
         first_name => 'Bilbo',