Update revision numbers in 'svn co' commands.
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Tutorial / CatalystBasics.pod
index 65fd1d6..a59bc41 100644 (file)
@@ -3,7 +3,6 @@
 Catalyst::Manual::Tutorial::CatalystBasics - Catalyst Tutorial - Part 2: Catalyst Application Development Basics
 
 
-
 =head1 OVERVIEW
 
 This is B<Part 2 of 9> for the Catalyst tutorial.
@@ -22,7 +21,7 @@ B<Catalyst Basics>
 
 =item 3
 
-L<Basic CRUD|Catalyst::Manual::Tutorial_BasicCRUD>
+L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
 
 =item 4
 
@@ -42,16 +41,15 @@ L<Testing|Catalyst::Manual::Tutorial::Testing>
 
 =item 8
 
-L<AdvancedCRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
+L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
 
 =item 9
 
-L<Appendicies|Catalyst::Manual::Tutorial::Appendicies>
+L<Appendices|Catalyst::Manual::Tutorial::Appendicies>
 
 =back
 
 
-
 =head1 DESCRIPTION
 
 In this part of the tutorial, we will create a very basic Catalyst web
@@ -69,24 +67,26 @@ skeletal structure of an application.
 
 Model/View/Controller (MVC) provides an architecture that facilitates a
 clean "separation of control" between the different portions of your
-application.  Given that many other documents cover this subject in
+application. Given that many other documents cover this subject in
 detail, MVC will not be discussed in depth here (for an excellent
 introduction to MVC and general Catalyst concepts, please see
-L<Catalyst::Manual::About|Catalyst::Manual::About>.  In short:
+L<Catalyst::Manual::About>. In short:
 
 =over 4
 
 =item * Model
 
-In most applications, the model equates to the objects that are created
-from and saved to your SQL database.
+The model usually represents a data store. In most applications, the
+model equates to the objects that are created from and saved to your SQL
+database.
 
 =item * View
 
 The view takes model objects and renders them into something for the end
-user to look at.  Normally this involves a template-generation tool that
+user to look at. Normally this involves a template-generation tool that
 creates HTML for the user's web browser, but it could easily be code
-that generates other forms such as PDF documents or Excel spreadsheets.
+that generates other forms such as PDF documents, e-mails, or Excel
+spreadsheets.
 
 =item * Controller
 
@@ -97,9 +97,9 @@ them to the necessary model and view.
 
 =item * ORM
 
-The use Object-Relational Mapping (ORM) technology for database access
-(specifically, ORM provides an automated means to persist and restore
-objects to/from a relational database).
+The use of Object-Relational Mapping (ORM) technology for database
+access. Specifically, ORM provides an automated and standardized means
+to persist and restore objects to/from a relational database.
 
 =back
 
@@ -107,37 +107,81 @@ B<TIP>: Note that all of the code for this part of the tutorial can be
 pulled from the Catalyst Subversion repository in one step with the
 following command:
 
-    svn checkout http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/Tutorial@###
+    svn checkout http://dev.catalyst.perl.org/repos/Catalyst/trunk/examples/Tutorial@4609 .
     IMPORTANT: Does not work yet.  Will be completed for final version.
 
 
-
 =head1 CREATE A CATALYST PROJECT
 
 Catalyst provides a number of helper scripts that can be used to quickly
-flesh out the basic structure of your application.  All Catalyst
-projects begin with the C<catalyst.pl> helper.
+flesh out the basic structure of your application. All Catalyst projects
+begin with the C<catalyst.pl> helper.
 
 In the case of this tutorial, use the Catalyst C<catalyst.pl> script to
 initialize the framework for an application called C<MyApp>:
 
     $ catalyst.pl MyApp
+    created "MyApp"
+    created "MyApp/script"
+    created "MyApp/lib"
+    created "MyApp/root"
+    ...
+    created "MyApp/script/myapp_create.pl"
     $ cd MyApp
 
 The C<catalyst.pl> helper script will display the names of the
 directories and files it creates.
 
-Though it's obviously too early for any significant celebration, we
-already have a functioning application.  Run the following command to
-run this application with the built-in development web server:
+Though it's too early for any significant celebration, we already have a
+functioning application. Run the following command to run this
+application with the built-in development web server:
 
-       $ script/myapp_server.pl
+    $ script/myapp_server.pl
+    [debug] Debug messages enabled
+    [debug] Loaded plugins:
+    .----------------------------------------------------------------------------.
+    | Catalyst::Plugin::ConfigLoader  0.06                                       |
+    | Catalyst::Plugin::Static::Simple  0.14                                     |
+    '----------------------------------------------------------------------------'
+    
+    [debug] Loaded dispatcher "Catalyst::Dispatcher"
+    [debug] Loaded engine "Catalyst::Engine::HTTP"
+    [debug] Found home "/root/dev/MyApp"
+    [debug] Loaded components:
+    .-----------------------------------------------------------------+----------.
+    | Class                                                           | Type     |
+    +-----------------------------------------------------------------+----------+
+    | MyApp::Controller::Root                                         | instance |
+    '-----------------------------------------------------------------+----------'
+    
+    [debug] Loaded Private actions:
+    .----------------------+--------------------------------------+--------------.
+    | Private              | Class                                | Method       |
+    +----------------------+--------------------------------------+--------------+
+    | /default             | MyApp::Controller::Root              | default      |
+    | /end                 | MyApp::Controller::Root              | end          |
+    '----------------------+--------------------------------------+--------------'
+    
+    [info] MyApp powered by Catalyst 5.70
+    You can connect to your server at http://localhost.localdomain:3000
+
+Point your web browser to L<http://localhost:3000> (substituting a 
+different hostname or IP address as appropriate) and you should be 
+greeted by the Catalyst welcome screen.  Information similar to the 
+following should be appended to the logging output of the development 
+server:
 
-Point your web browser to L<http://localhost:3000> (substituting a
-different hostname or IP address as appropriate) and you should be
-greeted by the Catalyst welcome screen.  Press Ctrl-C to break out of
-the development server.
+    [info] *** Request 1 (0.008/s) [2822] [Mon Jul  3 12:42:43 2006] ***
+    [debug] "GET" request for "/" from "127.0.0.1"
+    [info] Request took 0.154781s (6.461/s)
+    .----------------------------------------------------------------+-----------.
+    | Action                                                         | Time      |
+    +----------------------------------------------------------------+-----------+
+    | /default                                                       | 0.000006s |
+    | /end                                                           | 0.000007s |
+    '----------------------------------------------------------------+-----------'
 
+Press Ctrl-C to break out of the development server.
 
 
 =head1 CREATE A SQLITE DATABASE
@@ -191,7 +235,7 @@ in your editor and enter:
     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 documents.
+cutting and pasting example code from POD-based documents.
 
 Then use the following command to build a C<myapp.db> SQLite database:
 
@@ -233,7 +277,6 @@ required if you do a single SQL statement on the command line).  Use
 your OS command prompt.
 
 
-
 =head1 EDIT THE LIST OF CATALYST PLUGINS
 
 One of the greatest benefits of Catalyst is that it has such a large
@@ -258,7 +301,9 @@ this plugin 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).
+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.
@@ -267,7 +312,7 @@ messages.
 
 L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
 
-C<ConfigLoader> provides an automatic way to load your configurable
+C<ConfigLoader> provides an automatic way to load configurable
 parameters for your application from a central YAML file (versus having
 the values hard-coded inside your Perl modules).  If you have not been
 exposed to YAML before, it is a human-readable data serialization format
@@ -275,7 +320,6 @@ that can be used to read (and write) values to/from text files.  We will
 see how to use this feature of Catalyst during the authentication and
 authorization sections (Part 4 and Part 5).
 
-
 =item *
 
 L<Catalyst::Plugin::Static::Simple|Catalyst::Plugin::Static::Simple>
@@ -298,91 +342,69 @@ Replace it with:
             ConfigLoader
             Static::Simple
             
-            Dumper
             StackTrace
-            DefaultEnd
             /;
 
-This tells Catalyst to start using three new plugins:
+This tells Catalyst to start using one new plugin:
 
 =over 4
 
 =item * 
 
-L<Catalyst::Plugin::Dumper|Catalyst::Plugin::Dumper>
-
-Allows you to easily use L<Data::Dumper|Data::Dumper> to dump variables
-to the logs, for example:
-
-    $c->log->dumper($myvar);
-
-When running your application under the development server, the logs
-will be printed to your screen along with the other debug information
-generated by the C<-Debug> flag.
-
-=item * 
-
 L<Catalyst::Plugin::StackTrace|Catalyst::Plugin::StackTrace>
 
 Adds a stack trace to the standard Catalyst "debug screen" (this is the
 screen Catalyst sends to your browser when an error occurs).
 
-Note: L<Dumper|Catalyst::Plugin::Dumper> output appears on the
-console/telnet/SSH window where you issue the C<script/myapp_server.pl>
-command.  L<StackTrace|Catalyst::Plugin::StackTrace> output appears in
-your browser.
-
-=item * 
-
-L<Catalyst::Plugin::DefaultEnd|Catalyst::Plugin::DefaultEnd>
-
-Automatically provides a Catalyst "end action" that invokes your view at
-the end of each request.  Also allows you to add "dump_info=1" (precede
-with "?" or "&" depending on where it is in the URL) to I<force> the
-debug screen at the end of the Catalyst request processing cycle.
-
-TIP: Many Catalyst-related documents predate
-L<DefaultEnd|Catalyst::Plugin::DefaultEnd> and suggest that you add an
-C<end> action to your application class (C<MyApp.pm>) or Root.pm
-(C<MyApp/Controller/Root.pm>).  In most of these cases, you can convert
-to L<DefaultEnd|Catalyst::Plugin::DefaultEnd> by deleting the C<end>
-action and using the plugin instead.
+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.
 
 =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
+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.
 
+B<TIP:> You may see examples that include the
+L<Catalyst::Plugin::DefaultEnd|Catalyst::Plugin::DefaultEnd>
+plugins.  As of Catalyst 5.70, C<DefaultEnd> has been
+deprecated in favor of 
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>
+(as the name of the package suggests, C<RenderView> is not
+a plugin, but an action). The purpose of both is essentially the same: 
+forward processing to the view to be rendered.  Applications generated
+under 5.70 should automatically use C<RenderView> and "just work"
+for most applications.  For more information on C<RenderView> and 
+the various options for forwarding to your view logic, please refer 
+to the "Using RenderView for the Default View" section under 
+"CATALYST VIEWS" below.
 
 
 =head1 DATABASE ACCESS WITH C<DBIx::Class>
 
 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 DBI interface.  However,
-most Catalyst applications use some form of ORM technology to
+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 the traditional Perl ORM
-engine, 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.
-
-Note: See L<Catalyst::Model::CDBI| Catalyst:: Model::CDBI > for more
-information on using Catalyst with L<Class::DBI|Class::DBI>.  Catalyst
-can also be used with "plain old DBI"; see L<Catalyst::Model::DBI|
-Catalyst::Model::DBI>.
+Tony Bowden's L<Class::DBI|Class::DBI> has been the traditional 
+Perl ORM engine, 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.
 
+Note: See L<Catalyst:: Model::CDBI> for more information on using
+Catalyst with L<Class::DBI|Class::DBI>.
 
 =head2 Create a DBIC Schema File
 
 DBIx::Class uses a schema file to load other classes that represent the
 tables in your database (DBIC refers to these "table objects" as "result
-sources," see L<DBIx::Class::ResultSource|DBIx::Class::ResultSource>).
-In this case, we want to load the model object for the C<books>,
-C<book_authors>, and C<authors> tables created in the previous step.
+sources"; see L<DBIx::Class::ResultSource>).  In this case, we want to
+load the model object for the C<books>, C<book_authors>, and C<authors>
+tables created in the previous step.
 
 Open C<lib/MyAppDB.pm> in your editor and insert:
 
@@ -390,7 +412,7 @@ Open C<lib/MyAppDB.pm> in your editor and insert:
     
     =head1 NAME 
     
-    MyAppDB -- DBIC Schema Class
+    MyAppDB - DBIC Schema Class
     
     =cut
     
@@ -413,13 +435,13 @@ Open C<lib/MyAppDB.pm> in your editor and insert:
 
 B<Note:> C<__PACKAGE__> is just a shorthand way of referencing the name
 of the package where it is used.  Therefore, in C<MyAppDB.pm>,
-C<__PACKAGE> is equivalent to C<MyAppDB>
+C<__PACKAGE__> is equivalent to C<MyAppDB>.
 
 
 =head2 Create the DBIC "Result Source" Files
 
 In this step, we create "table classes" (again, these are called a
-"result source" classes in DBIC) that acts as model objects for the
+"result source" classes in DBIC) that act as model objects for the
 C<books>, C<book_authors>, and C<authors> tables in our database.
 
 First, create a directory to hold the class:
@@ -484,11 +506,10 @@ a book to its collection of authors.  Without it, we would have to
 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.
+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.
 
 Next, open C<lib/MyAppDB/Author.pm> in your editor and enter:
 
@@ -504,7 +525,7 @@ Next, open C<lib/MyAppDB/Author.pm> in your editor and enter:
     __PACKAGE__->add_columns(qw/id first_name last_name/);
     # Set the primary key for the table
     __PACKAGE__->set_primary_key(qw/id/);
-
+    
     #
     # Set relationships:
     #
@@ -567,7 +588,7 @@ Finally, open C<lib/MyAppDB/BookAuthor.pm> in your editor and enter:
     #     2) Name of the model class referenced by this relationship
     #     3) Column name in *this* table
     __PACKAGE__->belongs_to(book => 'MyAppDB::Book', 'book_id');
-
+    
     # belongs_to():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
@@ -585,7 +606,7 @@ Finally, open C<lib/MyAppDB/BookAuthor.pm> in your editor and enter:
     
     This is an object that represents a row in the 'book_authors' table of your 
     application database.  It uses DBIx::Class (aka, DBIC) to do ORM.
-
+    
     You probably won't need to use this class directly -- it will be automatically
     used by DBIC where joins are needed.
     
@@ -601,7 +622,6 @@ tables (e.g., C<books> and C<authors>) and a singular form for the model
 objects (e.g., C<Book> and C<Author>); however, Catalyst places no
 restrictions on the naming conventions you wish to use.
 
-
 =head2 Use C<Catalyst::Model::DBIC::Schema> To Load The Model Class
 
 When L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> is
@@ -609,20 +629,26 @@ in use, Catalyst essentially reads an existing copy of your database
 model and creates a new set of objects under C<MyApp::Model> for use
 inside of Catalyst.
 
-B<Note:> With
-L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> you
-essentially end up with two sets of model classes (only one of which you
-write... the other set is created automatically in memory when your
-Catalyst application initializes).  For this tutorial application, the
-important points to remember are: you write the I<result source> files
-in C<MyAppDB>, but I<within Catalyst> you use the I<automatically
+B<Note:> With 
+L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema> you 
+essentially end up with two sets of model classes (only one of which 
+you write... the other set is created automatically in memory when 
+your Catalyst application initializes).  For this tutorial application, 
+the important points to remember are: you write the I<result source> 
+files in C<MyAppDB>, but I<within Catalyst> you use the I<automatically 
 created model classes> in C<MyApp::Model>.
 
-Use the L<Catalyst::Helper::Model::DBIC::Schema|
-Catalyst::Helper::Model::DBIC::Schema > helper script to create the
-model class that loads up the model we created in the previous step:
+Use the 
+L<Catalyst::Helper::Model::DBIC::Schema|Catalyst::Helper::Model::DBIC::Schema> 
+helper script to create the model class that loads up the model we 
+created in the previous step:
 
     $ script/myapp_create.pl model MyAppDB DBIC::Schema MyAppDB dbi:SQLite:myapp.db '' '' '{ AutoCommit => 1 }'
+     exists "/root/dev/MyApp/script/../lib/MyApp/Model"
+     exists "/root/dev/MyApp/script/../t"
+    created "/root/dev/MyApp/script/../lib/MyApp/Model/MyAppDB.pm"
+    created "/root/dev/MyApp/script/../t/model_MyAppDB.t"
+
 
 Where the first C<MyAppDB> is the name of the class to be created by the
 helper in C<lib/MyApp/Model> and the second C<MyAppDB> is the name of
@@ -633,14 +659,20 @@ of MVC: C<Model>, C<View>, and C<Controller> [although older Catalyst
 applications often use the directories C<M>, C<V>, and C<C>]).
 
 
-
 =head1 CREATE A CATALYST CONTROLLER
 
-Controllers are where you write methods that respond to C<GET> and C<POST> messages from the user's web browser.
+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.
 
-Use the Catalyst C<create> script to add a controller for book-related actions:
+Use the Catalyst C<create> script to add a controller for book-related
+actions:
 
     $ script/myapp_create.pl controller Books
+     exists "/root/dev/MyApp/script/../lib/MyApp/Controller"
+     exists "/root/dev/MyApp/script/../t"
+    created "/root/dev/MyApp/script/../lib/MyApp/Controller/Books.pm"
+    created "/root/dev/MyApp/script/../t/controller_Books.t"
 
 Then edit C<lib/MyApp/Controller/Books.pm> and add the following method
 to the controller:
@@ -679,23 +711,24 @@ written as C<$c-E<gt>model('MyAppDB')-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 to provide additional information
-to the Catalyst dispatcher logic.
+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.
 
 
 =head1 CATALYST VIEWS
 
-Views are where you render output for display in the user's web browser
-(or possibly using other display technology).  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
+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|HTML::Template>
 (L<http://html-template.sourceforge.net>).
 
-
 =head2 Create a Catalyst View Using C<TTSITE>
 
 When using TT for the Catalyst view, there are two main helper scripts:
@@ -714,16 +747,22 @@ L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>
 
 Both are similar, but C<TT> merely 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 7).  Conversely, 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, etc.
+entirely up to you. (It also creates a C<t/view_TT.t> file for testing;
+test cases will be discussed in Part 7). 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.
 
 Enter the following command to enable the C<TTSite> style of view
-rendering for the tutorial:
+rendering for this tutorial:
 
     $ script/myapp_create.pl view TT TTSite
+     exists "/root/dev/MyApp/script/../lib/MyApp/View"
+     exists "/root/dev/MyApp/script/../t"
+    created "/root/dev/MyApp/script/../lib/MyApp/View/TT.pm"
+    created "/root/dev/MyApp/script/../root/lib"
+    ...
+    created "/root/dev/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
@@ -731,21 +770,144 @@ application.  Also take a look at C<lib/MyApp/View/TT.pm> for config
 values set by the C<TTSite> helper.
 
 B<TIP>: Note that TTSite does one thing that could confuse people who
-are used to the normal C<TT> Catalyst View: it redefines the Catalyst
-context object in templates from its usual C<c> to C<Catalyst>.  Also
-keep this in mind when looking at other Catalyst examples (they almost
-always use C<c>).  Note that Catalyst and TT I<do not complain> when you
-use the wrong name to access the context... it simply outputs blanks for
-that bogus logic.  Finally, be aware that this change in name I<only>
-applies to how the context object is accessed inside your TT templates,
+are used to the normal C<TT> Catalyst view: it redefines the Catalyst
+context object in templates from its usual C<c> to C<Catalyst>. When
+looking at other Catalyst examples, remember that they almost always use
+C<c>.  Note that Catalyst and TT I<do not complain> when you use the
+wrong name to access the context object...TT simply outputs blanks for
+that bogus logic (see next tip to change this behavior with TT C<DEBUG>
+options).  Finally, be aware that this change in name I<only>
+applies to how the context object is accessed inside your TT templates;
 your controllers will continue to use C<$c> (or whatever name you use
-when fetching the reference from C<@_> inside your methods).  (You can
+when fetching the reference from C<@_> inside your methods). (You can
 change back to the "default" behavior be removing the C<CATALYST_VAR>
 line from C<lib/MyApp/View/TT.pm>, but you will also have to edit
 C<root/lib/config/main> and C<root/lib/config/url>.  If you do this, be
 careful not to have a collision between your own C<c> variable and the
 Catalyst C<c> variable.)
 
+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<MyApp/View/TT.pm>:
+
+    __PACKAGE__->config({
+        CATALYST_VAR => 'Catalyst',
+        ...
+        DEBUG        => 'undef',
+        ...
+    });
+
+There are a variety of options you can use, such as 'undef', 'all', 
+'service', 'context', 'parser', 'provider', and 'service'.  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).
+
+
+=head2 Using C<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 v5.70 ships with a new mechanism, 
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>, that 
+automatically performs this operation.  If you look in 
+C<lib/MyApp/Controller/Root.pm>, you should see the this empty 
+definition for the C<sub end> method:
+
+    sub end : ActionClass('RenderView') {}
+
+The following bullet points provide a quick overview of the 
+C<RenderView> process:
+
+=over 4
+
+=item *
+
+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 
+"global" C<end> method in C<Root.pm> will be called.
+
+=item *
+
+Because the definition includes an C<ActionClass> attribute, the
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView> logic
+will be executed B<after> any code inside the definition of C<sub end>
+is run.  See L<Catalyst::Manual::Actions|Catalyst::Manual::Actions>
+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>.
+
+=back
+
+
+=head3 The History Leading Up To C<RenderView>
+
+Although C<RenderView> strikes a nice balance between default
+behavior and easy extensibility, it is a new feature that won't 
+appear in most existing Catalyst examples.  This section provides
+some brief background on the evolution of default view rendering
+logic with an eye to how they can be migrated to C<RenderView>:
+
+=over 4
+
+=item *
+
+Private C<end> Action in Application Class
+
+Older Catalyst-related documents often suggest that you add a "private 
+end action" to your application class (C<MyApp.pm>) or Root.pm 
+(C<MyApp/Controller/Root.pm>).  These examples should be easily 
+converted to L<RenderView|Catalyst::Action::RenderView> by simply adding 
+C<ActionClass('RenderView')> to the C<sub end> definition. If end sub is 
+defined in your application class (C<MyApp.pm>), you should also migrate 
+it to C<MyApp/Controller/Root.pm>.
+
+=item *
+
+L<Catalyst::Plugin::DefaultEnd|Catalyst::Plugin::DefaultEnd>
+
+C<DefaultEnd> represented the "next step" in passing processing from 
+your controller to your view.  It has the advantage of only requiring 
+that C<DefaultEnd> be added to the list of plugins in C<lib/MyApp.pm>. 
+It also allowed you to add "dump_info=1" (precede with "?" or "&" 
+depending on where it is in the URL) to I<force> the debug screen at the 
+end of the Catalyst request processing cycle.  However, it was more 
+difficult to extend the C<RenderView> mechanism, and is now deprecated.
+
+=item *
+
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>
+
+As discussed above, the current recommended approach to handling your 
+view logic relies on 
+L<Catalyst::Action::RenderView|Catalyst::Action::RenderView>.  Although 
+similar in first appearance to the "private end action" approach, it 
+utilizes Catalyst's "ActionClass" mechanism to provide both automatic 
+default behavior (you don't have to include a plugin as with 
+C<DefaultEnd>) and easy extensibility.  As with C<DefaultEnd>, it allows 
+you to add "dump_info=1" (precede with "?" or "&" depending on where it 
+is in the URL) to I<force> the debug screen at the end of the Catalyst 
+request processing cycle.
+
+=back
+
+It is recommended that all Catalyst applications use or migrate to
+the C<RenderView> approach.
 
 
 =head2 Globally Customize Every View
@@ -753,7 +915,7 @@ Catalyst C<c> variable.)
 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> update it to match the following (the two HTML
+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>
@@ -767,15 +929,15 @@ C<span> elements are new):
     <div id="footer">[% PROCESS site/footer %]</div>
 
 If we set either message in the Catalyst stash (e.g.,
-C<$c-E<gt>stash-E<gt>{status_msg} = 'Hello world'>) 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.
+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.
 
 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).
+Catalyst sessions in the Authentication part of the tutorial).
 
 
 =head2 Create a TT Template Page
@@ -807,16 +969,16 @@ Then open C<root/src/books/list.tt2> in your editor and enter:
         <td>[% book.title %]</td>
         <td>[% book.rating %]</td>
         <td>
-          [% # Print author count in parens. 'book.authors' uses the 'many_to_many' -%]
-          [% # relationship to retrieve all of the authors of a book. 'size' is a   -%]
-          [% # TT VMethod to get the number of elements in a list.                  -%]
-          ([% book.authors.size %])
-          [% # Use an alternate form of a FOREACH loop to display authors.          -%]
-          [% # _ below is the TT string concatenation operator.                     -%]
-          [% author.last_name _' ' FOREACH author = book.authors %]
-          [% # Note: if many_to_many relationship not used in Authors.pm, you could -%]
-          [% # have used the following to 'walk' through the 'join table objects'   -%]
-          [% # bk_author.author.last_name _' ' FOREACH bk_author = book.book_authors %]
+          [% # 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     -%]
+          [% # authors into the list.  Note that we make a bogus assignment to the   -%]
+          [% # 'unused' vbl to avoid printing the size of the list after each push.  -%]      
+          [% tt_authors = [ ];
+             unused = tt_authors.push(author.last_name) FOREACH author = book.authors %]
+          [% # Now use a TT 'virtual method' to display the author count in parens   -%]
+          ([% tt_authors.size %])
+          [% # Use another vmethod to join & print the names with comma separators   -%]
+          [% tt_authors.join(', ') %]
         </td>
       </tr>
     [% END -%]
@@ -826,12 +988,11 @@ 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 outer C<FOREACH> loop iterates through each C<book> model
 object and prints the C<title> and C<rating> fields.  An inner
-C<FOREACH> loop prints the last name of each author in a single table
-cell (a simple space is used between the names; in reality you would
-probably want to modify the code to use a comma as a separator).
+C<FOREACH> loop prints the last name of each author in a comma-separated
+list within a single table cell.
 
-If you are new to TT, the [% and %] tags are used to delimit "variable
-text".  TT supports a wide variety of directives for "calling" other
+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
@@ -850,7 +1011,6 @@ for both the file itself I<and> the C<$c-E<gt>stash-E<gt>{template} =
 consistency with the files already created by the C<TTSite> helper.
 
 
-
 =head1 RUN THE APPLICATION
 
 First, let's enable an environment variable option that causes
@@ -859,63 +1019,66 @@ DBIx::Class to dump the SQL statements it's using to access the database
 
     $ export DBIX_CLASS_STORAGE_DBI_DEBUG=1
 
+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 DBIX_CLASS_STORAGE_DBI_DEBUG 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|DBIx::Class::Manual::Troubleshooting>
-for details (including options to log to file vs. the Catalyst
-development server log.
+L<DBIx::Class::Manual::Troubleshooting> for details (including options
+to log to file instead of displaying to the Catalyst development server
+log).
 
 Then run the Catalyst "demo server" script:    
 
     $ script/myapp_server.pl
 
-You should get something like this:
+Your development server log output should display something like:
 
     $ script/myapp_server.pl
-    [Tue May 16 12:51:33 2006] [catalyst] [debug] Debug messages enabled
-    [Tue May 16 12:51:33 2006] [catalyst] [debug] Loaded plugins:
-    .------------------------------------------------------------------------------.
-    | Catalyst::Plugin::ConfigLoader 0.07                                          |
-    | Catalyst::Plugin::Static::Simple 0.14                                        |
-    | Catalyst::Plugin::Dumper 0.000002                                            |
-    | Catalyst::Plugin::StackTrace 0.04                                            |
-    | Catalyst::Plugin::DefaultEnd 0.06                                            |
-    '------------------------------------------------------------------------------'
-    
-    [Tue May 16 12:51:33 2006] [catalyst] [debug] Loaded dispatcher "Catalyst::Dispatcher"
-    [Tue May 16 12:51:33 2006] [catalyst] [debug] Loaded engine "Catalyst::Engine::HTTP"
-    [Tue May 16 12:51:33 2006] [catalyst] [debug] Found home "/home/me/MyApp"
-    [Tue May 16 12:51:37 2006] [catalyst] [debug] Loaded components:
-    .-------------------------------------------------------------------+----------.
-    | Class                                                             | Type     |
-    +-------------------------------------------------------------------+----------+
-    | MyApp::Controller::Books                                          | instance |
-    | MyApp::Controller::Root                                           | instance |
-    | MyApp::Model::MyAppDB                                             | instance |
-    | MyApp::Model::MyAppDB::Author                                     | class    |
-    | MyApp::Model::MyAppDB::Book                                       | class    |
-    | MyApp::Model::MyAppDB::BookAuthor                                 | class    |
-    | MyApp::View::TT                                                   | instance |
-    '-------------------------------------------------------------------+----------'
-    
-    [Tue May 16 12:51:37 2006] [catalyst] [debug] Loaded Private actions:
-    .----------------------+----------------------------------------+--------------.
-    | Private              | Class                                  | Method       |
-    +----------------------+----------------------------------------+--------------+
-    | /default             | MyApp::Controller::Root                | default      |
-    | /end                 | MyApp                                  | end          |
-    | /books/list          | MyApp::Controller::Books               | list         |
-    '----------------------+----------------------------------------+--------------'
-    
-    [Tue May 16 12:51:37 2006] [catalyst] [debug] Loaded Path actions:
-    .--------------------------------------+---------------------------------------.
-    | Path                                 | Private                               |
-    +--------------------------------------+---------------------------------------+
-    | /books/list                          | /books/list                           |
-    '--------------------------------------+---------------------------------------'
-    
-    [Tue May 16 12:51:37 2006] [catalyst] [info] MyApp powered by Catalyst 5.6902
-    You can connect to your server at http://localhost:3000
+    [debug] Debug messages enabled
+    [debug] Loaded plugins:
+    .----------------------------------------------------------------------------.
+    | Catalyst::Plugin::ConfigLoader  0.06                                       |
+    | Catalyst::Plugin::StackTrace  0.04                                         |
+    | Catalyst::Plugin::Static::Simple  0.14                                     |
+    '----------------------------------------------------------------------------'
+    
+    [debug] Loaded dispatcher "Catalyst::Dispatcher"
+    [debug] Loaded engine "Catalyst::Engine::HTTP"
+    [debug] Found home "/home/me/MyApp"
+    [debug] Loaded components:
+    .-----------------------------------------------------------------+----------.
+    | Class                                                           | Type     |
+    +-----------------------------------------------------------------+----------+
+    | MyApp::Controller::Books                                        | instance |
+    | MyApp::Controller::Root                                         | instance |
+    | MyApp::Model::MyAppDB                                           | instance |
+    | MyApp::Model::MyAppDB::Author                                   | class    |
+    | MyApp::Model::MyAppDB::Book                                     | class    |
+    | MyApp::Model::MyAppDB::BookAuthor                               | class    |
+    | MyApp::View::TT                                                 | instance |
+    '-----------------------------------------------------------------+----------'
+    
+    [debug] Loaded Private actions:
+    .----------------------+--------------------------------------+--------------.
+    | Private              | Class                                | Method       |
+    +----------------------+--------------------------------------+--------------+
+    | /default             | MyApp::Controller::Root              | default      |
+    | /end                 | MyApp::Controller::Root              | end          |
+    | /books/index         | MyApp::Controller::Books             | index        |
+    | /books/list          | MyApp::Controller::Books             | list         |
+    '----------------------+--------------------------------------+--------------'
+    
+    [debug] Loaded Path actions:
+    .-------------------------------------+--------------------------------------.
+    | Path                                | Private                              |
+    +-------------------------------------+--------------------------------------+
+    | /books/list                         | /books/list                          |
+    '-------------------------------------+--------------------------------------'
+    
+    [info] MyApp powered by Catalyst 5.70
+    You can connect to your server at http://localhost.localdomain:3000
 
 Some things you should note in the output above:
 
@@ -934,7 +1097,6 @@ C</books/list>.
 
 =back
 
-
 Point your browser to L<http://localhost:3000> and you should still get
 the Catalyst welcome page.
 
@@ -959,18 +1121,18 @@ legibility):
         JOIN authors author ON ( author.id = me.author_id ) 
         WHERE ( me.book_id = ? ): `1'
 
-You should see 10 such lines of debug output, two for each of the five
-author_id values (it pulls the data once for the count logic and another
-time to actually display the list).
+You should see 5 such lines of debug output as DBIC fetches the author 
+information for each book.
 
 
 =head1 AUTHOR
 
 Kennedy Clark, C<hkclark@gmail.com>
 
-Please report any errors, issues or suggestions to the author.
-
-Copyright 2006, Kennedy Clark, under Creative Commons License (L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
+Please report any errors, issues or suggestions to the author.  The
+most recent version of the Catlayst Tutorial can be found at
+L<http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Runtime/lib/Catalyst/Manual/Tutorial/>.
 
-Version: .94
+Copyright 2006, Kennedy Clark, under Creative Commons License
+(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).