Convert to more of a mixture of "DBIC" and "DBIx::Class" as per suggestion from Castaway
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / MoreCatalystBasics.pod
index a0d2b5a..f3ff00e 100644 (file)
@@ -1,11 +1,11 @@
 =head1 NAME
 
-Catalyst::Manual::Tutorial::MoreCatalystBasics - Catalyst Tutorial - Part 3: More Catalyst Application Development Basics
+Catalyst::Manual::Tutorial::MoreCatalystBasics - Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics
 
 
 =head1 OVERVIEW
 
-This is B<Part 3 of 10> for the Catalyst tutorial.
+This is B<Chapter 3 of 10> for the Catalyst tutorial.
 
 L<Tutorial Overview|Catalyst::Manual::Tutorial>
 
@@ -56,26 +56,33 @@ L<Appendices|Catalyst::Manual::Tutorial::Appendices>
 
 =head1 DESCRIPTION
 
-This part of the tutorial builds on the work done in Part 2 to explore 
-some features that are more typical of "real world" web applications. 
-From this part of the tutorial onward, we will be building a simple 
-book database application.  Although the application will be too 
-limited to be of use to anyone, it should provide a basic environment 
-where we can explore a variety of features used in virtually all web 
-applications.
+This chapter of the tutorial builds on the work done in Chapter 2 to 
+explore some features that are more typical of "real world" web 
+applications. From this chapter of the tutorial onward, we will be 
+building a simple book database application.  Although the application 
+will be too limited to be of use to anyone, it should provide a basic 
+environment where we can explore a variety of features used in 
+virtually all web applications.
 
-You can checkout the source code for this example from the catalyst
-subversion repository as per the instructions in
-L<Catalyst::Manual::Tutorial::Intro>
+You can check out the source code for this example from the Catalyst
+Subversion repository as per the instructions in
+L<Catalyst::Manual::Tutorial::Intro|Catalyst::Manual::Tutorial::Intro>.
+
+Please take a look at 
+L<Catalyst::Manual::Tutorial::Intro/CATALYST INSTALLATION> before 
+doing the rest of this tutorial.  Although the tutorial should work 
+correctly under most any recent version of Perl running on any 
+operating system, the tutorial has been written using Debian 5 and 
+tested to be sure it runs correctly in this environment.  
 
 
 =head1 CREATE A NEW APPLICATION
 
-The remainder of the tutorial will build an application call C<MyApp>. 
-Use the Catalyst C<catalyst.pl> script to initialize the framework for 
-an application called C<MyApp> (make sure you aren't still inside the 
-directory of the C<Hello> application from the previous part of the 
-tutorial):
+The remainder of the tutorial will build an application called C<MyApp>.
+First use the Catalyst C<catalyst.pl> script to initialize the framework
+for the C<MyApp> application (make sure you aren't still inside the
+directory of the C<Hello> application from the previous chapter of the
+tutorial or in a directory that already has a "MyApp" subdirectory):
 
     $ catalyst.pl MyApp
     created "MyApp"
@@ -86,25 +93,25 @@ tutorial):
     created "MyApp/script/myapp_create.pl"
     $ cd MyApp
 
-This creates a similar skeletal structure to what we saw in Part 2 of 
-the tutorial, except with C<MyApp> and C<myapp> substituted for 
+This creates a similar skeletal structure to what we saw in Chapter 2 of
+the tutorial, except with C<MyApp> and C<myapp> substituted for
 C<Hello> and C<hello>.
 
 
 =head1 EDIT THE LIST OF CATALYST PLUGINS
 
 One of the greatest benefits of Catalyst is that it has such a large
-library of plugins available.  Plugins are used to seamlessly integrate
-existing Perl modules into the overall Catalyst framework.  In general,
-they do this by adding additional methods to the C<context> object
-(generally written as C<$c>) that Catalyst passes to every component
-throughout the framework.
+library of plugins and base classes available.  Plugins are used to
+seamlessly integrate existing Perl modules into the overall Catalyst
+framework.  In general, they do this by adding additional methods to the
+C<context> object (generally written as C<$c>) that Catalyst passes to
+every component throughout the framework.
 
 By default, Catalyst enables three plugins/flags:
 
 =over 4
 
-=item * 
+=item *
 
 C<-Debug> Flag
 
@@ -112,12 +119,12 @@ Enables the Catalyst debug output you saw when we started the
 C<script/myapp_server.pl> development server earlier.  You can remove
 this item when you place your application into production.
 
-As you may have noticed, C<-Debug> is not a plugin, but a I<flag>.
-Although most of the items specified on the C<use Catalyst> line of your
-application class will be plugins, Catalyst supports a limited number of
-flag options (of these, C<-Debug> is the most common).  See the
-documentation for C<Catalyst.pm> to get details on other flags 
-(currently C<-Engine>, C<-Home>, and C<-Log>).
+As you may have noticed, C<-Debug> is not a plugin, but a I<flag>. 
+Although most of the items specified on the C<__PACKAGE__-E<gt>setup> 
+line of your application class will be plugins, Catalyst supports a 
+limited number of flag options (of these, C<-Debug> is the most 
+common).  See the documentation for C<Catalyst.pm> to get details on 
+other flags (currently C<-Engine>, C<-Home>, and C<-Log>).
 
 If you prefer, you can use the C<$c-E<gt>debug> method to enable debug
 messages.
@@ -125,7 +132,7 @@ messages.
 B<TIP>: Depending on your needs, it can be helpful to permanently
 remove C<-Debug> from C<lib/MyApp.pm> and then use the C<-d> option
 to C<script/myapp_server.pl> to re-enable it just for the development
-server.  We will not be using that approach in the tutorial, but feel 
+server.  We will not be using that approach in the tutorial, but feel
 free to make use of it in your own projects.
 
 =item *
@@ -138,93 +145,105 @@ L<Config::General|Config::General> file (versus having the values
 hard-coded inside your Perl modules).  Config::General uses syntax
 very similar to Apache configuration files.  We will see how to use
 this feature of Catalyst during the authentication and authorization
-sections (Part 5 and Part 6).
-
-B<IMPORTANT NOTE:> If you are following along in Ubuntu 8.04 or
-otherwise using a version of L<Catalyst::Devel|Catalyst::Devel> prior
-to version 1.06, you need to be aware that Catalyst changed from a
-default format of YAML to the more straightforward C<Config::General>
-format.  Because Catalyst has long supported both formats, this
-tutorial will simply use a configuration file called C<myapp.conf>
-instead of C<myapp.yml> and Catalyst will automatically use the new
-format.  Just be aware that earlier versions of Catalyst will still
-create the C<myapp.yml> file and that you will need to B<remove
-C<myapp.yml>> and create a new C<myapp.conf> file by hand, but
-otherwise this transition is very painless.  The default contents of
-C<myapp.conf> should only consist of one line: C<name MyApp>.  Also be
-aware that you can continue to use any format supported by
-L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader> and
-L<Config::Any|Config::Any>, including YAML -- Catalyst will
-automatically look for any of the supported configuration file
-formats.
-
-B<TIP>: This script can be useful for converting between configuration 
+sections (Chapter 5 and Chapter 6).
+
+B<IMPORTANT NOTE:> If you are using a version of 
+L<Catalyst::Devel|Catalyst::Devel> prior to version 1.06, be aware 
+that Catalyst changed the default format from YAML to the more 
+straightforward C<Config::General> style.  This tutorial uses the 
+newer C<myapp.conf> file for C<Config::General>. However, Catalyst 
+supports both formats and will automatically use either C<myapp.conf> 
+or C<myapp.yml> (or any other format supported by 
+L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader> and 
+L<Config::Any|Config::Any>).  If you are using a version of 
+Catalyst::Devel prior to 1.06, you can convert to the newer format by 
+simply creating the C<myapp.conf> file manually and deleting 
+C<myapp.yml>.  The default contents of the C<myapp.conf> you create 
+should only consist of one line: 
+
+    name MyApp
+
+B<TIP>: This script can be useful for converting between configuration
 formats:
 
-    perl -Ilib -e 'use MyApp; use Config::General; 
+    perl -Ilib -e 'use MyApp; use Config::General;
         Config::General->new->save_file("myapp.conf", MyApp->config);'
 
-B<NOTE:> The default C<myapp.conf> should look like:
-
-    name   MyApp
-
 =item *
 
 L<Catalyst::Plugin::Static::Simple|Catalyst::Plugin::Static::Simple>
 
-C<Static::Simple> provides an easy method of serving static content such
-as images and CSS files under the development server.
+C<Static::Simple> provides an easy way to serve static content, such
+as images and CSS files, from the development server.
 
 =back
 
-To modify the list of plugins, edit C<lib/MyApp.pm> (this file is
-generally referred to as your I<application class>) and delete the line
-with:
+For our application, we want to add one new plugin into the mix.  To 
+do this, edit C<lib/MyApp.pm> (this file is generally referred to as 
+your I<application class>) and delete the lines with:
 
-    use Catalyst qw/-Debug ConfigLoader Static::Simple/;
+    use Catalyst qw/-Debug
+                    ConfigLoader
+                    Static::Simple/;
 
-Replace it with:
+Then replace it with:
 
-    use Catalyst qw/
-                   -Debug
-                   ConfigLoader
-                   Static::Simple
+    # Load plugins
+    use Catalyst qw/-Debug
+                ConfigLoader
+                Static::Simple
+                
+                StackTrace
+                /;
 
-                   StackTrace
-                  /;
+B<Note:> Recent versions of C<Catalyst::Devel> have used a variety of 
+techniques to load these plugins/flags.  For example, you might see
+the following:
+
+    __PACKAGE__->setup(qw/-Debug ConfigLoader Static::Simple/);
+
+Don't let these variations confuse you -- they all accomplish the same 
+result.
+
+This tells Catalyst to start using one new plugin, 
+L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>, to add a 
+stack trace to the standard Catalyst "debug screen" (the screen 
+Catalyst sends to your browser when an error occurs). Be aware that 
+L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your 
+browser, not in the console window from which you're running your 
+application, which is where logging output usually goes.
 
-This tells Catalyst to start using one new plugin:
+B<Notes:> 
 
 =over 4
 
-=item * 
+=item *
+
+C<__PACKAGE__> is just a shorthand way of referencing the name of the 
+package where it is used.  Therefore, in C<MyApp.pm>, C<__PACKAGE__> 
+is equivalent to C<MyApp>.
 
-L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>
+=item *
 
-Adds a stack trace to the standard Catalyst "debug screen" (this is the
-screen Catalyst sends to your browser when an error occurs).
+You will want to disable L<StackTrace|Catalyst::Plugin::StackTrace> 
+before you put your application into production, but it can be helpful 
+during development.
 
-Note: L<StackTrace|Catalyst::Plugin::StackTrace> output appears in your
-browser, not in the console window from which you're running your
-application, which is where logging output usually goes.
+=item *
 
-B<Note:> You will want to disable 
-L<StackTrace|Catalyst::Plugin::StackTrace> before you put your 
-application into production, but it can be helpful during development.
+When specifying plugins on the C<__PACKAGE__-E<gt>setup> line, you can 
+omit C<Catalyst::Plugin::> from the name.  Additionally, you can 
+spread the plugin names across multiple lines as shown here, or place 
+them all on one (or more) lines as with the default configuration.
 
 =back
 
-Note that when specifying plugins on the C<use Catalyst> line, you can
-omit C<Catalyst::Plugin::> from the name.  Additionally, you can spread
-the plugin names across multiple lines as shown here, or place them all
-on one (or more) lines as with the default configuration.
-
 
 =head1 CREATE A CATALYST CONTROLLER
 
-As discussed earlier, controllers are where you write methods that 
-interact with user input.  Typically, controller methods respond to 
-C<GET> and C<POST> messages from the user's web browser.
+As discussed earlier, controllers are where you write methods that
+interact with user input.  Typically, controller methods respond to
+C<GET> and C<POST> requests from the user's web browser.
 
 Use the Catalyst C<create> script to add a controller for book-related
 actions:
@@ -235,15 +254,17 @@ actions:
     created "/home/me/MyApp/script/../lib/MyApp/Controller/Books.pm"
     created "/home/me/MyApp/script/../t/controller_Books.t"
 
-Then edit C<lib/MyApp/Controller/Books.pm> and add the following method
-to the controller:
+Then edit C<lib/MyApp/Controller/Books.pm> (as discussed in Chapter 2 of
+the Tutorial, Catalyst has a separate directory under C<lib/MyApp> for
+each of the three parts of MVC: C<Model>, C<View>, and C<Controller>)
+and add the following method to the controller:
 
     =head2 list
     
     Fetch all book objects and pass to books/list.tt2 in stash to be displayed
     
     =cut
-     
+    
     sub list : Local {
         # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
         # 'Context' that's used to 'glue together' the various components
@@ -252,66 +273,129 @@ to the controller:
     
         # Retrieve all of the book records as book model objects and store in the
         # stash where they can be accessed by the TT template
-        $c->stash->{books} = [$c->model('DB::Books')->all];
-        
+        # $c->stash->{books} = [$c->model('DB::Books')->all];
+        # But, for now, use this code until we create the model later
+        $c->stash->{books} = '';
+    
         # Set the TT template to use.  You will almost always want to do this
         # in your action methods (action methods respond to user input in
         # your controllers).
         $c->stash->{template} = 'books/list.tt2';
     }
 
-B<Note:> This won't actually work yet since you haven't set up your 
-model yet.  We will be covering the model soon.
-
-B<Note:> Programmers experienced with object-oriented Perl should 
-recognize C<$self> as a reference to the object where this method was 
-called.  On the other hand, C<$c> will be new to many Perl programmers 
-who have not used Catalyst before (it's sometimes written as 
-C<$context>).  The Context object is automatically passed to all 
-Catalyst components.  It is used to pass information between 
-components and provide access to Catalyst and plugin functionality.
-
-B<TIP>: You may see the C<$c-E<gt>model('DB::Book')> used above
-written as C<$c-E<gt>model('DB')-E<gt>resultset('Book')>.  The two
-are equivalent.
-
-B<Note:> Catalyst actions are regular Perl methods, but they make use 
-of Nicholas Clark's C<attributes> module (that's the C<: Local> next 
-to the C<sub list> in the code above) to provide additional 
-information to the Catalyst dispatcher logic.  Many newer Catalyst 
-applications are switching to the use of "Literal" C<:Path> actions 
-and C<Args> attribute in lieu of C<: Local> and C<: Private>.  For 
-example, C<sub any_method :Path :Args(0)> can be used instead of 
-C<sub index :Private> (because no path was supplied to C<Path> it 
-matches the "empty" URL in the namespace of that module... the same 
-thing C<sub index> would do) or C<sub list :Path('list') :Args(0)> 
-could be used instead of the C<sub list : Local> above (the C<list> 
-argument to C<Path> would make it match on the URL C<list> under 
-C<books>, the namespace of the current module).  See "Action Types" in 
-L<Catalyst::Manual::Intro|Catalyst::Manual::Intro> as well as Part 5 
-of this tutorial (Authentication) for additional information.  Another 
-popular but more advanced feature is C<Chained> actions that allow a 
-single URL to "chain together" multiple action method calls, each with 
-an appropriate number of arguments (see
-L<Catalyst::DispatchType::Chained|Catalyst::DispatchType::Chained>
-for details).
+B<TIP>: See Appendix 1 for tips on removing the leading spaces when
+cutting and pasting example code from POD-based documents.
+
+Programmers experienced with object-oriented Perl should recognize 
+C<$self> as a reference to the object where this method was called. 
+On the other hand, C<$c> will be new to many Perl programmers who have 
+not used Catalyst before (it's sometimes written as C<$context>).  The 
+Context object is automatically passed to all Catalyst components.  It 
+is used to pass information between components and provide access to 
+Catalyst and plugin functionality.
+
+Catalyst actions are regular Perl methods, but they make use of 
+attributes (the "C<: Local>" next to the "C<sub list>" in the code 
+above) to provide additional information to the Catalyst dispatcher 
+logic (note that the space between the colon and the attribute name is 
+optional; you will see attributes written both ways).  Most Catalyst 
+Controllers use one of five action types:
+
+=over 4
+
+=item *
+
+B<:Private> -- Use C<:Private> for methods that you want to make into 
+an action, but you do not want Catalyst to directly expose  
+to your users.  Catalyst will not map C<:Private> methods to a URI. 
+Use them for various sorts of "special" methods (the C<begin>, 
+C<auto>, etc. discussed below) or for methods you want to be able to 
+C<forward> or C<detach> to.  (If the method is a plain old "helper 
+method" that you don't want to be an action at all, then just define 
+the method without any attribute -- you can call it in your code, but 
+the Catalyst dispatcher will ignore it.)
+
+There are five types of "special" build-in C<:Private> actions: 
+C<begin>, C<end>, C<default>, C<index>, and C<auto>.
+
+=over 4
+
+=item *
+
+With C<begin>, C<end>, C<default>, C<index> private actions, only the
+most specific action of each type will be called.  For example, if you
+define a C<begin> action in your controller it will I<override> a
+C<begin> action in your application/root controller -- I<only> the
+action in your controller will be called.
+
+=item *
+
+Unlike the other actions where only a single method is called for each
+request, I<every> auto action along the chain of namespaces will be
+called.  Each C<auto> action will be called I<from the application/root
+controller down through the most specific class>.
+
+=back
+
+=item *
+
+B<:Path> -- C<:Path> actions let you map a method to an explicit URI 
+path.  For example, "C<:Path('list')>" in 
+C<lib/MyApp/Controller/Books.pm> would match on the URL 
+C<http://localhost:3000/books/list> but "C<:Path('/list')>" would match 
+on C<http://localhost:3000/list>.  You can use C<:Args()> to specify 
+how many arguments an action should accept.  See 
+L<Catalyst::Manual::Intro/Action_types> for more information and a few 
+examples.
+
+=item *
+
+B<:Local> -- C<:Local> is merely a shorthand for 
+"C<:Path('_name_of_method_')>".  For example, these are equivalent:
+"C<sub create_book :Local {...}>" and 
+"C<sub create_book :Path('create_book') {...}>".
+
+=item *
+
+B<:Global> -- C<:Global> is merely a shorthand for 
+"C<:Path('/_name_of_method_')>".  For example, these are equivalent:
+"C<sub create_book :Global {...}>" and 
+"C<sub create_book :Path('/create_book') {...}>".
+
+=item *
+
+B<:Chained> -- Newer Catalyst applications tend to use the Chained 
+dispatch form of action types because of its power and flexibility.  
+It allows a series of controller methods to be automatically dispatched
+to service a single user request.  See 
+L<Catalyst::Manual::Tutorial::BasicCRUD|Catalyst::Manual::Tutorial::BasicCRUD> 
+and L<Catalyst::DispatchType::Chained|Catalyst::DispatchType::Chained> 
+for more information on chained actions.
+
+=back
+
+You should refer to L<Catalyst::Manual::Intro/Action_types> for 
+additional information and for coverage of some lesser-used action 
+types not discussed here (C<Regex> and C<LocalRegex>).
 
 
 =head1 CATALYST VIEWS
 
-As mentioned in Part 2 of the tutorial, views are where you render 
-output, typically for display in the user's web browser, but also 
-possibly using other display output- generation systems.  As with 
-virtually every aspect of Catalyst, options abound when it comes to 
-the specific view technology you adopt inside your application. 
-However, most Catalyst applications use the Template Toolkit, known as 
-TT (for more information on TT, see 
-L<http://www.template-toolkit.org>). Other popular view technologies 
-include Mason (L<http://www.masonhq.com> and 
-L<http://www.masonbook.com>) and L<HTML::Template> 
-(L<http://html-template.sourceforge.net>).
+As mentioned in Chapter 2 of the tutorial, views are where you render
+output, typically for display in the user's web browser (but also
+possibly using into output-generation systems, such as PDF or JSON).
+The code in C<lib/MyApp/View> selects the I<type> of view to use, with
+the actual rendering template found in the C<root> directory.  As with
+virtually every aspect of Catalyst, options abound when it comes to the
+specific view technology you adopt inside your application. However,
+most Catalyst applications use the Template Toolkit, known as TT (for
+more information on TT, see L<http://www.template-toolkit.org>). Other
+somewhat popular view technologies include Mason
+(L<http://www.masonhq.com> and L<http://www.masonbook.com>) and
+L<HTML::Template> (L<http://html-template.sourceforge.net>).
+
 
-=head2 Create a Catalyst View Using C<TTSite>
+=head2 Create a Catalyst View
 
 When using TT for the Catalyst view, there are two main helper scripts:
 
@@ -327,108 +411,76 @@ L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>
 
 =back
 
-Both are similar, but C<TT> merely creates the C<lib/MyApp/View/TT.pm>
+Both helpers are similar. C<TT> creates the C<lib/MyApp/View/TT.pm>
 file and leaves the creation of any hierarchical template organization
 entirely up to you. (It also creates a C<t/view_TT.t> file for testing;
-test cases will be discussed in Part 8). The C<TTSite> helper creates a
-modular and hierarchical view layout with separate Template Toolkit (TT)
-files for common header and footer information, configuration values, a
-CSS stylesheet, and more.
-
-While TTSite is useful to bootstrap a project, we recommend that
-unless you know what you're doing or want to pretty much use the
-supplied templates as is, that you use the plain Template Toolkit view
-when starting a project from scratch.  This is because TTSite can be
-tricky to customize.  Additionally TT contains constructs that you
-need to learn yourself if you're going to be a serious user of TT.
-Our experience suggests that you're better off learning these from
-scratch.  We use TTSite here precisely because it is useful for
-bootstrap/prototype purposes.
-
-Enter the following command to enable the C<TTSite> style of view
+test cases will be discussed in Chapter 8.) C<TTSite>, on the other hand, 
+creates a modular and hierarchical view layout with
+separate Template Toolkit (TT) files for common header and footer
+information, configuration values, a CSS stylesheet, and more.
+
+While C<TTSite> was useful to bootstrap a project, its use is now
+deprecated and it should be considered historical.  For most Catalyst
+applications it adds redundant functionality and structure; many in the
+Catalyst community recommend that it's easier to learn both Catalyst and
+Template Toolkit if you use the more basic C<TT> approach.
+Consequently, this tutorial will use "plain old TT."
+
+Enter the following command to enable the C<TT> style of view
 rendering for this tutorial:
 
-    $ script/myapp_create.pl view TT TTSite
+    $ script/myapp_create.pl view TT TT
      exists "/home/me/MyApp/script/../lib/MyApp/View"
      exists "/home/me/MyApp/script/../t"
-    created "/home/me/MyApp/script/../lib/MyApp/View/TT.pm"
-    created "/home/me/MyApp/script/../root/lib"
-    ...
-    created "/home/me/MyApp/script/../root/src/ttsite.css"
-
-This puts a number of files in the C<root/lib> and C<root/src>
-directories that can be used to customize the look and feel of your
-application.  Also take a look at C<lib/MyApp/View/TT.pm> for config
-values set by the C<TTSite> helper.
-
-B<TIP>: When troubleshooting TT it can be helpful to enable variable
-C<DEBUG> options.  You can do this in a Catalyst environment by adding
-a C<DEBUG> line to the C<__PACKAGE__->config> declaration in 
-C<lib/MyApp/View/TT.pm>:
-
-    __PACKAGE__->config({
-        ...
-        DEBUG        => 'undef',
-        ...
-    });
-
-B<Note:> C<__PACKAGE__> is just a shorthand way of referencing the name
-of the package where it is used.  Therefore, in C<TT.pm>,
-C<__PACKAGE__> is equivalent to C<TT>.
-
-There are a variety of options you can use, such as 'undef', 'all', 
-'service', 'context', 'parser' and 'provider'.  See
-L<Template::Constants> for more information (remove the C<DEBUG_>
-portion of the name shown in the TT docs and convert to lower case
-for use inside Catalyst).
-
-B<NOTE:> B<Please be sure to disable TT debug options before 
-continuing the tutorial> (especially the 'undef' option -- leaving
-this enabled will conflict with several of the conventions used
-by this tutorial and TTSite to leave some variables undefined
-on purpose).
-
-
-=head2 Globally Customize Every View
-
-When using TTSite, files in the subdirectories of C<root/lib> can be
-used to make changes that will appear in every view.  For example, to
-display optional status and error messages in every view, edit
-C<root/lib/site/layout>, updating it to match the following (the two HTML
-C<span> elements are new):
-
-    <div id="header">[% PROCESS site/header %]</div>
-    
-    <div id="content">
-    <span class="message">[% status_msg %]</span>
-    <span class="error">[% error_msg %]</span>
-    [% content %]
-    </div>
-    
-    <div id="footer">[% PROCESS site/footer %]</div>
+     created "/home/me/MyApp/script/../lib/MyApp/View/TT.pm"
+     created "/home/me/MyApp/script/../t/view_TT.t"
 
-If we set either message in the Catalyst stash (e.g.,
-C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it will
-be displayed whenever any view used by that request is rendered.  The
-C<message> and C<error> CSS styles are automatically defined in
-C<root/src/ttsite.css> and can be customized to suit your needs.
+This simply creates a view called C<TT> (the second 'TT' argument) in 
+a file called C<TT.pm> (the first 'TT' argument). It is now up to you 
+to decide how you want to structure your view layout.  For the 
+tutorial, we will start with a very simple TT template to initially 
+demonstrate the concepts, but quickly migrate to a more typical 
+"wrapper page" type of configuration (where the "wrapper" controls the 
+overall "look and feel" of your site from a single file or set of 
+files).
 
-B<Note:> The Catalyst stash only lasts for a single HTTP request.  If
-you need to retain information across requests you can use
-L<Catalyst::Plugin::Session|Catalyst::Plugin::Session> (we will use
-Catalyst sessions in the Authentication part of the tutorial).
+Edit C<lib/MyApp/View/TT.pm> and you should see that the default
+contents contains something similar to the following:
 
+    __PACKAGE__->config(TEMPLATE_EXTENSION => '.tt');
 
-=head2 Create a TT Template Page
+And update it to match:
 
-To add a new page of content to the TTSite view hierarchy, just create a
-new C<.tt2> file in C<root/src>.  Only include HTML markup that goes
-inside the HTML <body> and </body> tags, TTSite will use the contents of
-C<root/lib/site> to add the top and bottom.
+    __PACKAGE__->config(
+        # Change default TT extension
+        TEMPLATE_EXTENSION => '.tt2',
+        # Set the location for TT files
+        INCLUDE_PATH => [
+                MyApp->path_to( 'root', 'src' ),
+            ],
+    );
+
+B<NOTE:> Make sure to add a comma after '.tt2' outside the single
+quote.
+
+This changes the default extension for Template Toolkit from '.tt' to
+'.tt2' and changes the base directory for your template files from
+C<root> to C<root/src>.  These changes from the default are done mostly
+to facilitate the application we're developing in this tutorial; as with
+most things Perl, there's more than one way to do it...
+
+B<Note:> We will use C<root/src> as the base directory for our 
+template files, which a full naming convention of 
+C<root/src/_controller_name_/_action_name_.tt2>.  Another popular option is to
+use C<root/> as the base (with a full filename pattern of 
+C<root/_controller_name_/_action_name_.tt2>).
+
+
+=head2 Create a TT Template Page
 
 First create a directory for book-related TT templates:
 
-    $ mkdir root/src/books
+    $ mkdir -p root/src/books
 
 Then create C<root/src/books/list.tt2> in your editor and enter:
 
@@ -437,7 +489,7 @@ Then create C<root/src/books/list.tt2> in your editor and enter:
     [% # it WILL eliminate a blank line if you view the HTML source.  It's purely   -%]
     [%- # optional, but both the beginning and the ending TT tags support chomping. -%]
     
-    [% # Provide a title to root/lib/site/header -%]
+    [% # Provide a title -%]
     [% META title = 'Book List' -%]
     
     <table>
@@ -447,40 +499,62 @@ Then create C<root/src/books/list.tt2> in your editor and enter:
       <tr>
         <td>[% book.title %]</td>
         <td>[% book.rating %]</td>
+        <td></td>
       </tr>
     [% END -%]
     </table>
 
 As indicated by the inline comments above, the C<META title> line uses
-TT's META feature to provide a title to C<root/lib/site/header>.
-Meanwhile, the C<FOREACH> loop iterates through each C<book> model
-object and prints the C<title> and C<rating> fields.
-
-If you are new to TT, the C<[%> and C<%]> tags are used to delimit TT
-code.  TT supports a wide variety of directives for "calling" other
-files, looping, conditional logic, etc.  In general, TT simplifies the
-usual range of Perl operators down to the single dot (C<.>) operator.
-This applies to operations as diverse as method calls, hash lookups, and
-list index values (see
-L<http://search.cpan.org/perldoc?Template::Manual::Variables>
-for details and examples).  In addition to the usual C<Template> module
-Pod documentation, you can access the TT manual at
+TT's META feature to provide a title to the "wrapper" that we will
+create later. Meanwhile, the C<FOREACH> loop iterates through each
+C<book> model object and prints the C<title> and C<rating> fields.
+
+The C<[%> and C<%]> tags are used to delimit Template Toolkit code.  TT
+supports a wide variety of directives for "calling" other files,
+looping, conditional logic, etc.  In general, TT simplifies the usual
+range of Perl operators down to the single dot (C<.>) operator.  This
+applies to operations as diverse as method calls, hash lookups, and list
+index values (see
+L<http://search.cpan.org/perldoc?Template::Manual::Variables> for
+details and examples).  In addition to the usual C<Template> module Pod
+documentation, you can access the TT manual at
 L<http://search.cpan.org/perldoc?Template::Manual>.
 
-B<NOTE:> The C<TTSite> helper creates several TT files using an
-extension of C<.tt2>. Most other Catalyst and TT examples use an
-extension of C<.tt>.  You can use either extension (or no extension at
-all) with TTSite and TT, just be sure to use the appropriate extension
-for both the file itself I<and> the C<$c-E<gt>stash-E<gt>{template} =
-...> line in your controller.  This document will use C<.tt2> for
-consistency with the files already created by the C<TTSite> helper.
+B<TIP:> While you can build all sorts of complex logic into your TT
+templates, you should in general keep the "code" part of your templates
+as simple as possible.  If you need more complex logic, create helper
+methods in your model that abstract out a set of code into a single call
+from your TT template.  (Note that the same is true of your controller
+logic as well -- complex sections of code in your controllers should
+often be pulled out and placed into your model objects.)
+
+
+=head2 Test Run The Application
+
+To test your work so far, first start the development server:
+
+    $ script/myapp_server.pl
+
+Then point your browser to L<http://localhost:3000> and you should
+still get the Catalyst welcome page.  Next, change the URL in your
+browser to L<http://localhost:3000/books/list>.  If you have
+everything working so far, you should see a web page that displays
+nothing other than our column headers for "Title", "Rating", and
+"Author(s)" -- we will not see any books until we get the database and
+model working below.
+
+If you run into problems getting your application to run correctly, it
+might be helpful to refer to some of the debugging techniques covered in
+the L<Debugging|Catalyst::Manual::Tutorial::Debugging> part of the
+tutorial.
 
 
 =head1 CREATE A SQLITE DATABASE
 
 In this step, we make a text file with the required SQL commands to
-create a database table and load some sample data.  Open C<myapp01.sql>
-in your editor and enter:
+create a database table and load some sample data.  We will use SQLite,
+a popular database that is lightweight and easy to use.  Open
+C<myapp01.sql> in your editor and enter:
 
     --
     -- Create a very simple database to hold book and author information
@@ -526,23 +600,20 @@ in your editor and enter:
     INSERT INTO book_authors VALUES (4, 7);
     INSERT INTO book_authors VALUES (5, 8);
 
-B<TIP>: See Appendix 1 for tips on removing the leading spaces when
-cutting and pasting example code from POD-based documents.
-
 Then use the following command to build a C<myapp.db> SQLite database:
 
     $ sqlite3 myapp.db < myapp01.sql
 
 If you need to create the database more than once, you probably want to
 issue the C<rm myapp.db> command to delete the database before you use
-the C<sqlite3 myapp.db < myapp01.sql> command.
+the C<sqlite3 myapp.db E<lt> myapp01.sql> command.
 
 Once the C<myapp.db> database file has been created and initialized, you
 can use the SQLite command line environment to do a quick dump of the
 database contents:
 
     $ sqlite3 myapp.db
-    SQLite version 3.4.2
+    SQLite version 3.5.9
     Enter ".help" for instructions
     sqlite> select * from books;
     1|CCSP SNRS Exam Certification Guide|5
@@ -568,82 +639,280 @@ required if you do a single SQL statement on the command line).  Use
 ".q" to exit from SQLite from the SQLite interactive mode and return to
 your OS command prompt.
 
+For using other databases, such as PostgreSQL or MySQL, see 
+L<Appendix 2|Catalyst::Manual::Tutorial::Appendices>.
+
+
+=head1 DATABASE ACCESS WITH DBIx::Class
+
+Catalyst can be used with virtually any form of datastore available 
+via Perl.  For example, L<Catalyst::Model::DBI|Catalyst::Model::DBI> 
+can be used to access databases through the traditional Perl C<DBI> 
+interface or you can use a model to access files of any type on the 
+filesystem.  However, most Catalyst applications use some form of 
+object-relational mapping (ORM) technology to create objects 
+associated with tables in a relational database.  Matt Trout's 
+L<DBIx::Class|DBIx::Class> (abbreviated as "DBIC") has rapidly emerged 
+as the Perl-based ORM technology of choice. Most new Catalyst 
+applications rely on DBIx::Class, as will this tutorial.
+
+Although DBIx::Class has included support for a C<create=dynamic> mode 
+to automatically read the database structure every time the 
+application starts, it's use is no longer recommended.  While it can 
+make for "flashy" demos, the use of the C<create=static> mode we use 
+below can be implemented just as quickly and provides many advantages 
+(such as the ability to add your own methods to the overall DBIC 
+framework, a technique that we see in Chapter 4).
+
+
+=head2 Make Sure You Have a Recent Version of the DBIx::Class Model
+
+First, let's be sure we have a recent version of the DBIC helper,
+L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema>, by
+running this command:
 
-=head1 DATABASE ACCESS WITH C<DBIx::Class>
+    $ perl -MCatalyst::Model::DBIC::Schema -e \
+        'print "$Catalyst::Model::DBIC::Schema::VERSION\n"'
+    0.23
 
-Catalyst can be used with virtually any form of persistent datastore
-available via Perl.  For example, 
-L<Catalyst::Model::DBI|Catalyst::Model::DBI> can be used to
-easily access databases through the traditional Perl C<DBI> interface.
-However, most Catalyst applications use some form of ORM technology to
-automatically create and save model objects as they are used.  Although
-Tony Bowden's L<Class::DBI|Class::DBI> has been a popular choice 
-in the past, Matt Trout's L<DBIx::Class|DBIx::Class> (abbreviated 
-as "DBIC") has rapidly emerged as the Perl-based ORM technology of choice.  
-Most new Catalyst applications rely on DBIC, as will this tutorial.
+If you don't have version 0.23 or higher, please run this command
+to install it directly from CPAN:
+
+    $ sudo cpan Catalyst::Model::DBIC::Schema
+
+And re-run the version print command to verify that you are now at 
+0.23 or higher.
+
+
+=head2 Create Static DBIx::Class Schema Files
+
+Use the model helper with the C<create=static> option to read the 
+database with 
+L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> and 
+automatically build the required files for us:
+
+    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
+        create=static components=TimeStamp dbi:SQLite:myapp.db
+     exists "/home/me/MyApp/script/../lib/MyApp/Model"
+     exists "/home/me/MyApp/script/../t"
+    Dumping manual schema for MyApp::Schema to directory /home/me/MyApp/script/../lib ...
+    Schema dump completed.
+    created "/home/me/MyApp/script/../lib/MyApp/Model/DB.pm"
+    created "/home/me/MyApp/script/../t/model_DB.t"
+
+The C<script/myapp_create.pl> command breaks down like this:
+
+=over 4
+
+=item *
+
+C<DB> is the name of the model class to be created by the helper in 
+C<lib/MyApp/Model>.
+
+=item *
+
+C<DBIC::Schema> is the type of the model to create.
+
+=item *
+
+C<MyApp::Schema> is the name of the DBIC schema file written to
+C<lib/MyApp/Schema.pm>.
+
+=item *
+
+C<create=static> causes 
+L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> to 
+load the schema as it runs and then write that information out
+into files.
+
+=item *
+
+C<components=TimeStamp> causes the help to include the 
+L<DBIx::Class::TimeStamp|DBIx::Class::TimeStamp> DBIC component.
+
+=item *
+
+And finally, C<dbi:SQLite:myapp.db> is the standard DBI connect string 
+for use with SQLite.
+
+=back
+
+If you look in the C<lib/MyApp/Schema.pm> file, you will find that it 
+only contains a call to the C<load_namespaces> method.  You will also 
+find that C<lib/MyApp> contains a C<Schema> subdirectory, which then 
+has a subdirectory called "Result".  This "Result" subdirectory then 
+has files named according to each of the tables in our simple database 
+(C<Authors.pm>, C<BookAuthors.pm>, and C<Books.pm>).  These three 
+files are called "Result Classes" in DBIx::Class nomenclature. Although the 
+Result Class files are named after tables in our database, the classes 
+correspond to the I<row-level data> that is returned by DBIC (more on 
+this later, especially in 
+L<Catalyst::Manual::Tutorial::BasicCRUD/EXPLORING THE POWER OF DBIC>).
+
+The idea with the Result Source files created under 
+C<lib/MyApp/Schema/Result> by the C<create=static> option is to only 
+edit the files below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> 
+warning. If you place all of your changes below that point in the 
+file, you can regenerate the automatically created information at the 
+top of each file should your database structure get updated.
+
+Also note the "flow" of the model information across the various files 
+and directories.  Catalyst will initially load the model from 
+C<lib/MyApp/Model/DB.pm>.  This file contains a reference to 
+C<lib/MyApp/Schema.pm>, so that file is loaded next.  Finally, the 
+call to C<load_namespaces> in C<Schema.pm> will load each of the 
+"Result Class" files from the C<lib/MyApp/Schema/Result> subdirectory. 
+The final outcome is that Catalyst will dynamically create three 
+table-specific Catalyst models every time the application starts (you 
+can see these three model files listed in the debug output generated 
+when you launch the application).
+
+B<NOTE:> Older versions of 
+L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> use the 
+deprecated DBIx::Class C<load_classes> technique instead of the newer 
+C<load_namspaces>.  For new applications, please try to use 
+C<load_namespaces> since it more easily supports a very useful DBIC 
+technique called "ResultSet Classes."  If you need to convert an 
+existing application from "load_classes" to "load_namespaces," you can 
+use this process to automate the migration (but first make sure you 
+have v0.23 C<Catalyst::Model::DBIC::Schema> as discussed above):
+
+    $ # First delete the existing schema file to disable "compatibility" mode
+    $ rm lib/MyApp/Schema.pm
+    $
+    $ # Then re-run the helper to build the files for "load_namespaces"
+    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
+        create=static components=TimeStamp dbi:SQLite:myapp.db
+    $
+    $ # Now convert the existing files over
+    $ cd lib/MyApp/Schema
+    $ perl -MIO::All -e 'for (@ARGV) { my $s < io($_); $s =~ s/.*\n\# You can replace.*?\n//s;
+          $s =~ s/'MyApp::Schema::/'MyApp::Schema::Result::/g; my $d < io("Result/$_");
+          $d =~ s/1;\n?//; "$d$s" > io("Result/$_"); }' *.pm
+    $ cd ../../..
+    $
+    $ # And finally delete the old files
+    $ rm lib/MyApp/Schema/*.pm
 
-=head2 Create a dynamic DBIC Model
+The "C<perl -MIO::ALL ...>" script will copy all the customized 
+relationship (and other) information below "C<# DO NOT MODIFY>" line 
+from the old files in C<lib/MyApp/Schema> to the new files in 
+C<lib/MyApp/Schema/Result> (we will be starting to add some 
+"customized relationship information in the section below).
 
-Use the C<create=dynamic> model helper option to build a model that 
-dynamically reads your database structure every time the application
-starts:
+The C<script/myapp_create.pl> command breaks down like this:
 
-    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=dynamic dbi:SQLite:myapp.db
-     exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
-     exists "/home/kclark/dev/MyApp/script/../t"
-     exists "/home/kclark/dev/MyApp/script/../lib/MyApp"
-    created "/home/kclark/dev/MyApp/script/../lib/MyApp/Schema.pm"
-    created "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/DB.pm"
-    created "/home/kclark/dev/MyApp/script/../t/model_DB.t"
+=over 4
 
+=item *
 
 C<DB> is the name of the model class to be created by the helper in 
-C<lib/MyApp/Model> (Catalyst has a separate directory under C<lib/MyApp> 
-for each of the three parts of MVC: C<Model>, C<View>, and C<Controller>).  
-C<DBIC::Schema> is the type of the model to create. 
-C<MyApp::Schema> is the name of the DBIC schema file written to 
-C<lib/MyApp/Schema.pm>.  Because we specified C<create=dynamic> 
-to the helper, it use L<DBIx::Class::Schema::Loader> to dynamically load 
-the schema information from the database every time the application 
-starts.  And finally, C<dbi:SQLite:myapp.db> is the standard DBI connect 
-string for use with SQLite.
+C<lib/MyApp/Model>.
+
+=item *
+
+C<DBIC::Schema> is the type of the model to create.
+
+=item *
+
+C<MyApp::Schema> is the name of the DBIC schema file written to
+C<lib/MyApp/Schema.pm>.
+
+=item *
+
+Because we specified C<create=dynamic> to the helper, it use 
+L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> to 
+dynamically load the schema information from the database every time 
+the application starts.
+
+=item *
+
+And finally, C<dbi:SQLite:myapp.db> is the standard DBI connect string 
+for use with SQLite.
+
+=back
+
+
+=head1 ENABLE THE MODEL IN THE CONTROLLER
+
+Open C<lib/MyApp/Controller/Books.pm> and un-comment the model code we 
+left disabled earlier so that your version matches the following (un-
+comment the line containing C<[$c-E<gt>model('DB::Books')-E<gt>all]> 
+and delete the next 2 lines):
+
+    =head2 list
+    
+    Fetch all book objects and pass to books/list.tt2 in stash to be displayed
+    
+    =cut
+    
+    sub list : Local {
+        # Retrieve the usual Perl OO '$self' for this object. $c is the Catalyst
+        # 'Context' that's used to 'glue together' the various components
+        # that make up the application
+        my ($self, $c) = @_;
+    
+        # Retrieve all of the book records as book model objects and store in the
+        # stash where they can be accessed by the TT template
+        $c->stash->{books} = [$c->model('DB::Books')->all];
+    
+        # Set the TT template to use.  You will almost always want to do this
+        # in your action methods (action methods respond to user input in
+        # your controllers).
+        $c->stash->{template} = 'books/list.tt2';
+    }
+
+B<TIP>: You may see the C<$c-E<gt>model('DB::Books')> un-commented 
+above written as C<$c-E<gt>model('DB')-E<gt>resultset('Books')>.  The 
+two are equivalent.  Either way, C<$c-E<gt>model> returns a 
+L<DBIx::Class::ResultSet|DBIx::Class::ResultSet> which handles queries 
+against the database and iterating over the set of results that is 
+returned.
+
+We are using the C<-E<gt>all> to fetch all of the books.  DBIC 
+supports a wide variety of more advanced operations to easily do 
+things like filtering and sorting the results.  For example, the 
+following could be used to sort the results by descending title:
+
+    $c->model('DB::Books')->search({}, {order_by => 'title DESC'});
 
-B<NOTE:> Although the C<create=dynamic> option to the DBIC helper
-makes for a nifty demonstration, is only really suitable for very
-small applications. After this demonstration, you should almost always
-use the C<create=static> option that we switch to below.
+Some other examples are provided in 
+L<DBIx::Class::Manual::Cookbook/Complex WHERE clauses>, with 
+additional information found at L<DBIx::Class::ResultSet/search>, 
+L<DBIx::Class::Manual::FAQ/Searching>, 
+L<DBIx::Class::Manual::Intro|DBIx::Class::Manual::Intro> 
+and L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema>.
 
 
-=head1 RUN THE APPLICATION
+=head2 Test Run The Application
 
-First, let's enable an environment variable option that causes
-DBIx::Class to dump the SQL statements it's using to access the database
-(this option can provide extremely helpful troubleshooting information):
+First, let's enable an environment variable that causes DBIx::Class to 
+dump the SQL statements used to access the database.  This is a 
+helpful trick when you are trying to debug your database-oriented 
+code:
 
     $ export DBIC_TRACE=1
 
-This assumes you are using BASH as your shell -- adjust accordingly if
+This assumes you are using bash as your shell -- adjust accordingly if
 you are using a different shell (for example, under tcsh, use
 C<setenv DBIC_TRACE 1>).
 
 B<NOTE:> You can also set this in your code using
 C<$class-E<gt>storage-E<gt>debug(1);>.  See
 L<DBIx::Class::Manual::Troubleshooting> for details (including options
-to log to file instead of displaying to the Catalyst development server
+to log to a file instead of displaying to the Catalyst development server
 log).
 
-Then run the Catalyst "demo server" script:    
+Then launch the Catalyst development server.  The log output should
+display something like:
 
     $ script/myapp_server.pl
-
-Your development server log output should display something like:
-
-    $script/myapp_server.pl
     [debug] Debug messages enabled
+    [debug] Statistics enabled
     [debug] Loaded plugins:
     .----------------------------------------------------------------------------.
-    | Catalyst::Plugin::ConfigLoader  0.17                                       |
-    | Catalyst::Plugin::StackTrace  0.06                                         |
+    | Catalyst::Plugin::ConfigLoader  0.20                                       |
+    | Catalyst::Plugin::StackTrace  0.08                                         |
     | Catalyst::Plugin::Static::Simple  0.20                                     |
     '----------------------------------------------------------------------------'
     
@@ -670,6 +939,7 @@ Your development server log output should display something like:
     +----------------------+--------------------------------------+--------------+
     | /default             | MyApp::Controller::Root              | default      |
     | /end                 | MyApp::Controller::Root              | end          |
+    | /index               | MyApp::Controller::Root              | index        |
     | /books/index         | MyApp::Controller::Books             | index        |
     | /books/list          | MyApp::Controller::Books             | list         |
     '----------------------+--------------------------------------+--------------'
@@ -678,31 +948,34 @@ Your development server log output should display something like:
     .-------------------------------------+--------------------------------------.
     | Path                                | Private                              |
     +-------------------------------------+--------------------------------------+
+    | /                                   | /default                             |
+    | /                                   | /index                               |
+    | /books                              | /books/index                         |
     | /books/list                         | /books/list                          |
     '-------------------------------------+--------------------------------------'
     
-    [info] MyApp powered by Catalyst 5.7011
-    You can connect to your server at http://localhost:3000
-
-B<NOTE:> Be sure you run the C<script/myapp_server.pl> command from 
-the 'base' directory of your application, not inside the C<script> 
-directory itself or it will not be able to locate the C<myapp.db> 
-database file.  You can use a fully qualified or a relative path to 
-locate the database file, but we did not specify that when we ran the 
+    [info] MyApp powered by Catalyst 5.71000
+    You can connect to your server at http://debian:3000
+
+B<NOTE:> Be sure you run the C<script/myapp_server.pl> command from
+the 'base' directory of your application, not inside the C<script>
+directory itself or it will not be able to locate the C<myapp.db>
+database file.  You can use a fully qualified or a relative path to
+locate the database file, but we did not specify that when we ran the
 model helper earlier.
 
 Some things you should note in the output above:
 
 =over 4
 
-=item * 
+=item *
 
-Catalyst::Model::DBIC::Schema dynamically created three model classes, 
-one to represent each of the three tables in our database 
+Catalyst::Model::DBIC::Schema dynamically created three model classes,
+one to represent each of the three tables in our database
 (C<MyApp::Model::DB::Authors>, C<MyApp::Model::DB::BookAuthors>,
 and C<MyApp::Model::DB::Books>).
 
-=item * 
+=item *
 
 The "list" action in our Books controller showed up with a path of
 C</books/list>.
@@ -714,12 +987,12 @@ the Catalyst welcome page.
 
 Next, to view the book list, change the URL in your browser to
 L<http://localhost:3000/books/list>. You should get a list of the five
-books loaded by the C<myapp01.sql> script above, with TTSite providing
-the formatting for the very simple output we generated in our template.
-The rating for each book should appear on each row.
+books loaded by the C<myapp01.sql> script above without any formatting.
+The rating for each book should appear on each row, but the "Author(s)"
+column will still be blank (we will fill that in later).
 
-Also notice in the output of the C<script/myapp_server.pl> that DBIC
-used the following SQL to retrieve the data:
+Also notice in the output of the C<script/myapp_server.pl> that 
+DBIx::Class used the following SQL to retrieve the data:
 
     SELECT me.id, me.title, me.rating FROM books me
 
@@ -730,91 +1003,204 @@ Continue on to future sections and we will develop the application
 more fully.
 
 
-=head1 A STATIC DATABASE MODEL WITH C<DBIx::Class>
+=head1 CREATE A WRAPPER FOR THE VIEW
 
-=head2 Create Static DBIC Schema Files
+When using TT, you can (and should) create a wrapper that will
+literally wrap content around each of your templates.  This is
+certainly useful as you have one main source for changing things that
+will appear across your entire site/application instead of having to
+edit many individual files.
 
-Unlike the previous section where we had DBIC automatically discover the 
-structure of the database every time the application started, here we 
-will use static schema files for more control.  This is typical of most 
-"real world" applications.
 
-One option would be to create a separate schema file for each table in
-the database, however, lets use the same L<DBIx::Class::Schema::Loader>
-used earlier with C<create=dynamic> to build the static files for us.
-First, lets remove the schema file created earlier:
+=head2 Configure TT.pm For The Wrapper
 
-    $ rm lib/MyApp/Schema.pm 
+In order to create a wrapper, you must first edit your TT view and
+tell it where to find your wrapper file. Your TT view is located in
+C<lib/MyApp/View/TT.pm>.
 
-Now regenerate the schema using the C<create=static> option:
+Edit C<lib/MyApp/View/TT.pm> and change it to match the following:
 
-    $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema create=static dbi:SQLite:myapp.db
-     exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model"
-     exists "/home/kclark/dev/MyApp/script/../t"
-    Dumping manual schema for MyApp::Schema to directory /home/kclark/dev/MyApp/script/../lib ...
-    Schema dump completed.
-     exists "/home/kclark/dev/MyApp/script/../lib/MyApp/Model/DB.pm"
-
-We could have also deleted C<lib/MyApp/Model/DB.pm>, but it would 
-have regenerated the same file (note the C<exists> in the output above).
-If you take a look at C<lib/MyApp/Model/DB.pm>, it simply contains
-a reference to the actual schema file in C<lib/MyApp/Schema.pm>
-along with the database connect string.
-
-If you look in the C<lib/MyApp/Schema> directory, you will find that 
-C<DB.pm> is no longer using L<DBIx::Class::Schema::Loader> as its 
-base class (L<DBIx::Class::Schema::Loader> is only being used by the 
-helper to load the schema once and then create the static files for us) 
-and that it only contains a call to the C<load_classes> method.  You 
-will also find that C<lib/MyApp/Schema> contains a C<Schema> 
-subdirectory, with one file inside this directory for each of the tables 
-in our simple database (C<Authors.pm>, C<BookAuthors.pm>, and 
-C<Books.pm>).  These three files were created based on the information
-found by L<DBIx::Class::Schema::Loader> as the helper ran.
-
-The idea with all of the files created under C<lib/MyApp/Schema> by the 
-C<create=static> option is to only edit the files below the C<# DO NOT 
-MODIFY THIS OR ANYTHING ABOVE!> warning.  If you place all of your 
-changes below that point in the file, you can regenerate the 
-auto-generated information at the top of each file should your database 
-structure get updated.
+    __PACKAGE__->config(
+        # Change default TT extension
+        TEMPLATE_EXTENSION => '.tt2',
+        # Set the location for TT files
+        INCLUDE_PATH => [
+                MyApp->path_to( 'root', 'src' ),
+            ],
+        # Set to 1 for detailed timer stats in your HTML as comments
+        TIMER              => 0,
+        # This is your wrapper template located in the 'root/src'
+        WRAPPER => 'wrapper.tt2',
+    );
 
-Also note the "flow" of the model information across the various files 
-and directories.  Catalyst will initially load the model from 
-C<lib/MyApp/Model/DB.pm>.  This file contains a reference to
-C<lib/MyApp/Schema.pm>, so that file is loaded next.  Finally,
-the call to C<load_classes> in that file will load each of the 
-table-specific "results source" files from the C<lib/MyApp/Schema>
-subdirectory.  These three table-specific DBIC schema files will then be 
-used to create three table-specific Catalyst models every time the 
-application starts (you can see these three model files listed in
-the debug output generated when you launch the application).
 
+=head2 Create the Wrapper Template File and Stylesheet
+
+Next you need to set up your wrapper template.  Basically, you'll want
+to take the overall layout of your site and put it into this file.
+For the tutorial, open C<root/src/wrapper.tt2> and input the following:
 
-=head2 Updating the Generated DBIC Schema Files
+    <?xml version="1.0" encoding="UTF-8"?>
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+    <head>
+    <title>[% template.title or "My Catalyst App!" %]</title>
+    <link rel="stylesheet" href="[% c.uri_for('/static/css/main.css') %]" />
+    </head>
+    
+    <body>
+    <div id="outer">
+    <div id="header">
+        [%# Your logo could go here -%]
+        <img src="[% c.uri_for('/static/images/btn_88x31_powered.png') %]" />
+        [%# Insert the page title -%]
+        <h1>[% template.title or site.title %]</h1>
+    </div>
+    
+    <div id="bodyblock">
+    <div id="menu">
+        Navigation:
+        <ul>
+            <li><a href="[% c.uri_for('/books/list') %]">Home</a></li>
+            <li><a href="[% c.uri_for('/') %]" title="Catalyst Welcome Page">Welcome</a></li>
+        </ul>
+    </div><!-- end menu -->
+    
+    <div id="content">
+        [%# Status and error messages %]
+        <span class="message">[% status_msg %]</span>
+        <span class="error">[% error_msg %]</span>
+        [%# This is where TT will stick all of your template's contents. -%]
+        [% content %]
+    </div><!-- end content -->
+    </div><!-- end bodyblock -->
+    
+    <div id="footer">Copyright (c) your name goes here</div>
+    </div><!-- end outer -->
+    
+    </body>
+    </html>
 
+Notice the status and error message sections in the code above:
 
-Let's manually add some relationship information to the auto-generated
-schema files.  First edit C<lib/MyApp/Schema/Books.pm> and
-add the following text below the C<# You can replace this text...> 
-comment:
+    <span class="status">[% status_msg %]</span>
+    <span class="error">[% error_msg %]</span>
+
+If we set either message in the Catalyst stash (e.g.,
+C<$c-E<gt>stash-E<gt>{status_msg} = 'Request was successful!'>) it
+will be displayed whenever any view used by that request is rendered.
+The C<message> and C<error> CSS styles can be customized to suit your
+needs in the C<root/static/css/main.css> file we create below.
+
+B<Notes:> 
+
+=over 4
+
+=item *
+
+The Catalyst stash only lasts for a single HTTP request.  If
+you need to retain information across requests you can use
+L<Catalyst::Plugin::Session|Catalyst::Plugin::Session> (we will use
+Catalyst sessions in the Authentication chapter of the tutorial).
+
+=item *
+
+Although it is beyond the scope of this tutorial, you may wish to use
+a JavaScript or AJAX tool such as jQuery (L<http://www.jquery.com>) or
+Dojo (L<http://www.dojotoolkit.org>).
+
+=back
+
+
+=head3 Create A Basic Stylesheet
+
+First create a central location for stylesheets under the static
+directory:
+
+    $ mkdir root/static/css
+
+Then open the file C<root/static/css/main.css> (the file referenced in
+the stylesheet href link of our wrapper above) and add the following
+content:
+
+    #header {
+        text-align: center;
+    }
+    #header h1 {
+        margin: 0;
+    }
+    #header img {
+        float: right;
+    }
+    #footer {
+        text-align: center;
+        font-style: italic;
+        padding-top: 20px;
+    }
+    #menu {
+        font-weight: bold;
+        background-color: #ddd;
+    }
+    #menu ul {
+        list-style: none;
+        float: left;
+        margin: 0;
+        padding: 0 0 50% 5px;
+        font-weight: normal;
+        background-color: #ddd;
+        width: 100px;
+    }
+    #content {
+        margin-left: 120px;
+    }
+    .message {
+        color: #390;
+    }
+    .error {
+        color: #f00;
+    }
+
+You may wish to check out a "CSS Framework" like Emastic
+(L<http://code.google.com/p/emastic/>) as a way to quickly
+provide lots of high-quality CSS functionality.
+
+
+=head2 Test Run The Application
+
+Restart the development server and hit "Reload" in your web browser
+and you should now see a formatted version of our basic book list.
+Although our wrapper and stylesheet are obviously very simple, you
+should see how it allows us to control the overall look of an entire
+website from two central files.  To add new pages to the site, just
+provide a template that fills in the C<content> section of our wrapper
+template -- the wrapper will provide the overall feel of the page.
+
+
+=head2 Updating the Generated DBIx::Class Result Class Files
+
+Let's manually add some relationship information to the auto-generated 
+Result Class files. (Note: if you are using a database other than 
+SQLite, such as PostgreSQL, then the relationship could have been 
+automatically placed in the Result Class files.  If so, you can skip 
+this step.)  First edit C<lib/MyApp/Schema/Result/Books.pm> and add the 
+following text below the C<# You can replace this text...> comment:
 
     #
     # Set relationships:
-    #   
+    #
     
     # has_many():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
-    #     3) Column name in *foreign* table
-    __PACKAGE__->has_many(book_authors => 'MyApp::Schema::BookAuthors', 'book_id');
+    #     3) Column name in *foreign* table (aka, foreign key in peer table)
+    __PACKAGE__->has_many(book_authors => 'MyApp::Schema::Result::BookAuthors', 'book_id');
     
     # many_to_many():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
-    #     2) Name of has_many() relationship this many_to_many() is shortcut for 
-    #     3) Name of belongs_to() relationship in model class of has_many() above 
+    #     2) Name of has_many() relationship this many_to_many() is shortcut for
+    #     3) Name of belongs_to() relationship in model class of has_many() above
     #   You must already have the has_many() defined to use a many_to_many().
     __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
 
@@ -824,19 +1210,31 @@ file.  As with any Perl package, we need to end the last line with
 a statement that evaluates to C<true>.  This is customarily done with
 C<1;> on a line by itself.
 
-This code defines both a C<has_many> and a C<many_to_many> relationship. 
-The C<many_to_many> relationship is optional, but it makes it easier to 
-map a book to its collection of authors.  Without it, we would have to 
-"walk" though the C<book_authors> table as in C<$book-E<gt>book_authors-
-E<gt>first-E<gt>author-E<gt>last_name> (we will see examples on how to 
-use DBIC objects in your code soon, but note that because C<$book-
-E<gt>book_authors> can return multiple authors, we have to use C<first> 
-to display a single author). C<many_to_many> allows us to use the 
-shorter C<$book-E<gt>authors-E<gt>first-E<gt>last_name>. Note that you 
-cannot define a C<many_to_many> relationship without also having the 
-C<has_many> relationship in place.
-
-Then edit C<lib/MyApp/Schema/Authors.pm> and add relationship
+C<Important Note:> Although this tutorial uses plural names for both 
+the names of the SQL tables and therefore the Result Classes (after 
+all, C<Schema::Loader> automatically named the Result Classes from the 
+names of the SQL tables it found), DBIx::Class users prefer singular 
+names for these items.  B<Please try to use singular table and DBIC 
+model/Result Class names in your applications.>  This tutorial will 
+migrate to singular names as soon as possible (patches welcomed). 
+B<Note that while singular is preferred for the DBIC model, plural is 
+perfectly acceptable for the names of the controller classes.>  After 
+all, the C<Books.pm> controller operates on multiple books.
+
+This code defines both a C<has_many> and a C<many_to_many> 
+relationship. The C<many_to_many> relationship is optional, but it 
+makes it easier to map a book to its collection of authors.  Without 
+it, we would have to "walk" though the C<book_authors> table as in 
+C<$book-E<gt>book_authors-E<gt>first-E<gt>author-E<gt>last_name> (we 
+will see examples on how to use DBIx::Class objects in your code soon, 
+but note that because C<$book-E<gt>book_authors> can return multiple 
+authors, we have to use C<first> to display a single author). 
+C<many_to_many> allows us to use the shorter C<$book-E<gt>authors-
+E<gt>first-E<gt>last_name>. Note that you cannot define a 
+C<many_to_many> relationship without also having the C<has_many> 
+relationship in place.
+
+Then edit C<lib/MyApp/Schema/Result/Authors.pm> and add relationship
 information as follows (again, be careful to put in above the C<1;> but
 below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
 
@@ -846,21 +1244,21 @@ below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
     
     # has_many():
     #   args:
-    #     1) Name of relationship, DBIC will create accessor with this name
+    #     1) Name of relationship, DBIC will create an accessor with this name
     #     2) Name of the model class referenced by this relationship
-    #     3) Column name in *foreign* table
-    __PACKAGE__->has_many(book_author => 'MyApp::Schema::BookAuthors', 'author_id');
+    #     3) Column name in *foreign* table (aka, foreign key in peer table)
+    __PACKAGE__->has_many(book_author => 'MyApp::Schema::Result::BookAuthors', 'author_id');
     
     # many_to_many():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of has_many() relationship this many_to_many() is shortcut for
-    #     3) Name of belongs_to() relationship in model class of has_many() above 
+    #     3) Name of belongs_to() relationship in model class of has_many() above
     #   You must already have the has_many() defined to use a many_to_many().
     __PACKAGE__->many_to_many(books => 'book_author', 'book');
 
-Finally, do the same for the "join table," 
-C<lib/MyApp/Schema/BookAuthors.pm>:
+Finally, do the same for the "join table,"
+C<lib/MyApp/Schema/Result/BookAuthors.pm>:
 
     #
     # Set relationships:
@@ -871,58 +1269,46 @@ C<lib/MyApp/Schema/BookAuthors.pm>:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
-    __PACKAGE__->belongs_to(book => 'MyApp::Schema::Books', 'book_id');
+    __PACKAGE__->belongs_to(book => 'MyApp::Schema::Result::Books', 'book_id');
     
     # belongs_to():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
-    __PACKAGE__->belongs_to(author => 'MyApp::Schema::Authors', 'author_id');
+    __PACKAGE__->belongs_to(author => 'MyApp::Schema::Result::Authors', 'author_id');
 
 
-=head1 RUN THE APPLICATION
+=head2 Run The Application
 
-Run the Catalyst "demo server" script with the C<DBIC_TRACE> option
-(it might still be enabled from earlier in the tutorial, but here
-is an alternate way to specify the option just in case):
+Run the Catalyst development server script with the C<DBIC_TRACE> option
+(it might still be enabled from earlier in the tutorial, but here is an
+alternate way to specify the option just in case):
 
     $ DBIC_TRACE=1 script/myapp_server.pl
 
-Make sure that the application loads correctly and that you see the 
-three dynamically created model class (one for each of the 
-table-specific schema classes we created).
+Make sure that the application loads correctly and that you see the
+three dynamically created model class (one for each of the
+Result Classes we created).
 
-Then hit the URL L<http://localhost:3000/books/list> and be sure that
-the book list is displayed.
+Then hit the URL L<http://localhost:3000/books/list> with your browser 
+and be sure that the book list is displayed via the relationships 
+established above. You can leave the development server running for 
+the next step if you wish.
 
-
-=head1 RUNNING THE APPLICATION FROM THE COMMAND LINE
-
-In some situations, it can be useful to run your application and 
-display a page without using a browser.  Catalyst lets you do this 
-using the C<scripts/myapp_test.pl> script.  Just supply the URL you 
-wish to display and it will run that request through the normal 
-controller dispatch logic and use the appropriate view to render the 
-output (obviously, complex pages may dump a lot of text to your 
-terminal window).  For example, if you type:
-
-    $ script/myapp_test.pl "/books/list"
-
-You should get the same text as if you visited 
-L<http://localhost:3000/books/list> with the normal development server 
-and asked your browser to view the page source.
+B<Note:> You will not see the authors yet because the view does not yet 
+use the new relations. Read on to the next section where we update the 
+template to do that.
 
 
 =head1 UPDATING THE VIEW
 
-Let's add a new column to our book list page that takes advantage of
-the relationship information we manually added to our schema files
-in the previous section.  Edit C<root/src/books/list.tt2> add add the
-following code below the existing table cell that contains
-C<book.rating> (IOW, add a new table cell below the existing two 
-C<td> cells):
+Let's add a new column to our book list page that takes advantage of 
+the relationship information we manually added to our schema files in 
+the previous section.  Edit C<root/src/books/list.tt2> and replace
+the "empty" tabase cell with the following:
 
+    ...
     <td>
       [% # First initialize a TT variable to hold a list.  Then use a TT FOREACH -%]
       [% # loop in 'side effect notation' to load just the last names of the     -%]
@@ -939,45 +1325,82 @@ C<td> cells):
       [% # Use another TT vmethod to join & print the names & comma separators   -%]
       [% tt_authors.join(', ') | html %]
     </td>
+    ...
 
-Then hit C<Ctrl+R> in your browser (note that you don't need to reload 
+Then hit "Reload" in your browser (note that you don't need to reload 
 the development server or use the C<-r> option when updating TT 
-templates) and you should now see the the number of authors each book 
-along with a comma-separated list of the author's last names.  
+templates) and you should now see the number of authors each book has 
+along with a comma-separated list of the authors' last names.  (If you 
+didn't leave the development server running from the previous step, 
+you will obviously need to start it before you can refresh your 
+browser window.)
+
+If you are still running the development server with C<DBIC_TRACE>
+enabled, you should also now see five more C<SELECT> statements in the
+debug output (one for each book as the authors are being retrieved by
+DBIx::Class):
+
+    SELECT me.id, me.title, me.rating FROM books me:
+    SELECT author.id, author.first_name, author.last_name FROM book_authors me  
+    JOIN authors author ON ( author.id = me.author_id ) WHERE ( me.book_id = ? ): '1'
+    SELECT author.id, author.first_name, author.last_name FROM book_authors me  
+    JOIN authors author ON ( author.id = me.author_id ) WHERE ( me.book_id = ? ): '2'
+    SELECT author.id, author.first_name, author.last_name FROM book_authors me  
+    JOIN authors author ON ( author.id = me.author_id ) WHERE ( me.book_id = ? ): '3'
+    SELECT author.id, author.first_name, author.last_name FROM book_authors me  
+    JOIN authors author ON ( author.id = me.author_id ) WHERE ( me.book_id = ? ): '4'
+    SELECT author.id, author.first_name, author.last_name FROM book_authors me  
+    JOIN authors author ON ( author.id = me.author_id ) WHERE ( me.book_id = ? ): '5'
+
+Also note in C<root/src/books/list.tt2> that we are using "| html", a 
+type of TT filter, to escape characters such as E<lt> and E<gt> to &lt; 
+and &gt; and avoid various types of dangerous hacks against your 
+application.  In a real application, you would probably want to put 
+"| html" at the end of every field where a user has control over the 
+information that can appear in that field (and can therefore inject 
+markup or code if you don't "neutralize" those fields).  In addition to 
+"| html", Template Toolkit has a variety of other useful filters that 
+can found in the documentation for 
+L<Template::Filters|Template::Filters>.
+
+
+=head1 RUNNING THE APPLICATION FROM THE COMMAND LINE
 
-If you are still running the development server with C<DBIC_TRACE> 
-enabled, you should also now see five more C<SELECT> statements in the 
-debug output (one for each book as the authors are being retrieved by 
-DBIC).
+In some situations, it can be useful to run your application and
+display a page without using a browser.  Catalyst lets you do this
+using the C<scripts/myapp_test.pl> script.  Just supply the URL you
+wish to display and it will run that request through the normal
+controller dispatch logic and use the appropriate view to render the
+output (obviously, complex pages may dump a lot of text to your
+terminal window).  For example, if you type:
 
-Also note that we are using "| html", a type of TT filter, to escape 
-characters such as E<lt> and E<gt> to &lt; and &gt; and avoid various
-types of dangerous hacks against your application.  In a real 
-application, you would probably want to put "| html" at the end of 
-every field where a user has control over the information that can 
-appear in that field (and can therefore inject markup or code if you
-don't "neutralize" those fields).  In addition to "| html", Template
-Toolkit has a variety of other useful filters that can found in the
-documentation for L<Template::Filters|Template::Filters>.
+    $ script/myapp_test.pl "/books/list"
 
+You should get the same text as if you visited
+L<http://localhost:3000/books/list> with the normal development server
+and asked your browser to view the page source.
 
-=head2 Using C<RenderView> for the Default View
 
-B<NOTE: The rest of this part of the tutorial is optional.  You can 
-skip to Part 4, L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>, 
+=head1 OPTIONAL INFORMATION
+
+B<NOTE: The rest of this chapter of the tutorial is optional.  You can
+skip to Chapter 4, L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>,
 if you wish.>
 
-Once your controller logic has processed the request from a user, it 
-forwards processing to your view in order to generate the appropriate 
+
+=head2 Using 'RenderView' for the Default View
+
+Once your controller logic has processed the request from a user, it
+forwards processing to your view in order to generate the appropriate
 response output.  Catalyst uses
-L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> by 
-default to automatically performs this operation.  If you look in 
-C<lib/MyApp/Controller/Root.pm>, you should see the empty 
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> by
+default to automatically perform this operation.  If you look in
+C<lib/MyApp/Controller/Root.pm>, you should see the empty
 definition for the C<sub end> method:
 
     sub end : ActionClass('RenderView') {}
 
-The following bullet points provide a quick overview of the 
+The following bullet points provide a quick overview of the
 C<RenderView> process:
 
 =over 4
@@ -988,10 +1411,10 @@ C<Root.pm> is designed to hold application-wide logic.
 
 =item *
 
-At the end of a given user request, Catalyst will call the most specific 
-C<end> method that's appropriate.  For example, if the controller for a 
-request has an C<end> method defined, it will be called.  However, if 
-the controller does not define a controller-specific C<end> method, the 
+At the end of a given user request, Catalyst will call the most specific
+C<end> method that's appropriate.  For example, if the controller for a
+request has an C<end> method defined, it will be called.  However, if
+the controller does not define a controller-specific C<end> method, the
 "global" C<end> method in C<Root.pm> will be called.
 
 =item *
@@ -1004,25 +1427,25 @@ for more information on C<ActionClass>.
 
 =item *
 
-Because C<sub end> is empty, this effectively just runs the default 
-logic in C<RenderView>.  However, you can easily extend the 
-C<RenderView> logic by adding your own code inside the empty method body 
-(C<{}>) created by the Catalyst Helpers when we first ran the 
-C<catalyst.pl> to initialize our application.  See 
-L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> for more 
-detailed information on how to extended C<RenderView> in C<sub end>.
+Because C<sub end> is empty, this effectively just runs the default
+logic in C<RenderView>.  However, you can easily extend the
+C<RenderView> logic by adding your own code inside the empty method body
+(C<{}>) created by the Catalyst Helpers when we first ran the
+C<catalyst.pl> to initialize our application.  See
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> for more
+detailed information on how to extend C<RenderView> in C<sub end>.
 
 =back
 
 
 =head2 Using The Default Template Name
 
-By default, C<Catalyst::View::TT> will look for a template that uses the 
-same name as your controller action, allowing you to save the step of 
-manually specifying the template name in each action.  For example, this 
-would allow us to remove the 
-C<$c-E<gt>stash-E<gt>{template} = 'books/list.tt2';> line of our 
-C<list> action in the Books controller.  Open 
+By default, C<Catalyst::View::TT> will look for a template that uses the
+same name as your controller action, allowing you to save the step of
+manually specifying the template name in each action.  For example, this
+would allow us to remove the
+C<$c-E<gt>stash-E<gt>{template} = 'books/list.tt2';> line of our
+C<list> action in the Books controller.  Open
 C<lib/MyApp/Controller/Books.pm> in your editor and comment out this line
 to match the following (only the C<$c-E<gt>stash-E<gt>{template}> line
 has changed):
@@ -1049,35 +1472,18 @@ has changed):
         #$c->stash->{template} = 'books/list.tt2';
     }
 
-C<Catalyst::View::TT> defaults to looking for a template with no 
-extension.  In our case, we need to override this to look for an 
-extension of C<.tt2>.  Open C<lib/MyApp/View/TT.pm> and add the 
-C<TEMPLATE_EXTENSION> definition as follows:
 
-    __PACKAGE__->config({
-        CATALYST_VAR => 'Catalyst',
-        INCLUDE_PATH => [
-            MyApp->path_to( 'root', 'src' ),
-            MyApp->path_to( 'root', 'lib' )
-        ],
-        PRE_PROCESS  => 'config/main',
-        WRAPPER      => 'site/wrapper',
-        ERROR        => 'error.tt2',
-        TIMER        => 0,
-        TEMPLATE_EXTENSION => '.tt2',
-    });
-
-You should now be able to restart the development server as per the 
+You should now be able to restart the development server as per the
 previous section and access the L<http://localhost:3000/books/list>
 as before.
 
 B<NOTE:> Please note that if you use the default template technique,
 you will B<not> be able to use either the C<$c-E<gt>forward> or
-the C<$c-E<gt>detach> mechanisms (these are discussed in Part 2 and 
-Part 9 of the Tutorial).
+the C<$c-E<gt>detach> mechanisms (these are discussed in Chapter 2 and
+Chapter 9 of the Tutorial).
 
 
-=head2 Return To A Manually-Specified Template
+=head2 Return To A Manually Specified Template
 
 In order to be able to use C<$c-E<gt>forward> and C<$c-E<gt>detach>
 later in the tutorial, you should remove the comment from the
@@ -1085,10 +1491,10 @@ statement in C<sub list> in C<lib/MyApp/Controller/Books.pm>:
 
     $c->stash->{template} = 'books/list.tt2';
 
-Then delete the C<TEMPLATE_EXTENSION> line in  
+Then delete the C<TEMPLATE_EXTENSION> line in
 C<lib/MyApp/View/TT.pm>.
 
-You should then be able to restart the development server and 
+You should then be able to restart the development server and
 access L<http://localhost:3000/books/list> in the same manner as
 with earlier sections.
 
@@ -1099,8 +1505,7 @@ Kennedy Clark, C<hkclark@gmail.com>
 
 Please report any errors, issues or suggestions to the author.  The
 most recent version of the Catalyst Tutorial can be found at
-L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Manual/lib/Catalyst/Manual/Tutorial/>.
+L<http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Manual/5.70/trunk/lib/Catalyst/Manual/Tutorial/>.
 
 Copyright 2006-2008, Kennedy Clark, under Creative Commons License
 (L<http://creativecommons.org/licenses/by-sa/3.0/us/>).
-