Move mention of different "stash styles" to Ch2
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / 03_MoreCatalystBasics.pod
index aef37db..e8da3f6 100644 (file)
@@ -91,21 +91,25 @@ tutorial or in a directory that already has a "MyApp" subdirectory):
     created "MyApp/root"
     ...
     created "MyApp/script/myapp_create.pl"
+    Change to application directory and Run "perl Makefile.PL" to make sure your install is complete
     $ cd MyApp
 
 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>.
+C<Hello> and C<hello>.  (As noted in Chapter 2, omit the ".pl" from 
+the command if you are using Strawberry Perl.)
 
 
 =head1 EDIT THE LIST OF CATALYST PLUGINS
 
-One of the greatest benefits of Catalyst is that it has such a large
-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.
+One of the greatest benefits of Catalyst is that it has such a large 
+library of bases classes and plugins available that you can use easily 
+add functionality to your application. 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:
 
@@ -119,15 +123,31 @@ 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>. 
+To be technically correct, it turns out that 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.
+If you prefer, there are several other ways to enable debug output:
+
+=over 4
+
+=item *
+
+Use the C<$c-E<gt>debug> method
+
+=item *
+
+The C<-d> option to C<script/myapp_server.pl>
+
+=item *
+
+The C<CATALYST_DEBUG=1> environment variable (or set it to
+zero to templorarily disable debug output).
+
+=back
 
 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
@@ -182,20 +202,22 @@ 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
+    /;
 
 Then replace it with:
 
     # Load plugins
     use Catalyst qw/
-                    -Debug
-                    ConfigLoader
-                    Static::Simple
-                
-                    StackTrace
-                    /;
+        -Debug
+        ConfigLoader
+        Static::Simple
+    
+        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
@@ -206,7 +228,7 @@ the following:
 Don't let these variations confuse you -- they all accomplish the same 
 result.
 
-This tells Catalyst to start using one new plugin, 
+This tells Catalyst to start using one additional 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 
@@ -214,8 +236,8 @@ 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.
 
-Make sure that when adding new plugins that you include them as a new
-dependancies within the Makefile.PL file. For example, after adding
+Make sure when adding new plugins you also include them as a new
+dependency within the Makefile.PL file. For example, after adding
 the StackTrace plugin the Makefile.PL should include the following
 line:
 
@@ -240,10 +262,9 @@ during development.
 
 =item *
 
-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.
+When specifying plugins, 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 line.
 
 =back
 
@@ -274,7 +295,7 @@ and add the following method to the controller:
     
     =cut
     
-    sub list : Local {
+    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
@@ -289,7 +310,7 @@ and add the following method to the controller:
         # 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';
+        $c->stash(template => 'books/list.tt2');
     }
 
 B<TIP>: See Appendix 1 for tips on removing the leading spaces when
@@ -304,7 +325,7 @@ 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 
+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 
@@ -315,7 +336,7 @@ Controllers use one of five action types:
 =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  
+an action, but you do not want Catalyst to directly expose  the method 
 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 
@@ -351,11 +372,11 @@ controller down through the most specific class>.
 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.
+C<http://localhost:3000/books/list>, but "C<:Path('/list')>" would 
+match on C<http://localhost:3000/list> (because of the leading slash). 
+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 examples.
 
 =item *
 
@@ -406,34 +427,11 @@ L<HTML::Template> (L<http://html-template.sourceforge.net>).
 
 =head2 Create a Catalyst View
 
-When using TT for the Catalyst view, there are two main helper scripts:
-
-=over 4
-
-=item *
-
-L<Catalyst::Helper::View::TT|Catalyst::Helper::View::TT>
-
-=item *
-
-L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>
-
-=back
-
-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 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."
+When using TT for the Catalyst view, the main helper script
+is L<Catalyst::Helper::View::TT|Catalyst::Helper::View::TT>.
+You may also come across references to 
+L<Catalyst::Helper::View::TTSite|Catalyst::Helper::View::TTSite>,
+but its use is now deprecated.
 
 Enter the following command to enable the C<TT> style of view
 rendering for this tutorial:
@@ -472,14 +470,15 @@ And update it to match:
 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...
+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>.  Stick with these conventions for the 
+tutorial, but feel free to use whatever options you desire in your 
+applications (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 
+template files, with 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>).
@@ -521,28 +520,32 @@ 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
+range of Perl operators down to the single dot (".") 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
+details and examples).  In addition to the usual L<Template> module Pod
 documentation, you can access the TT manual at
 L<http://search.cpan.org/perldoc?Template::Manual>.
 
-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.)
+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.)  In Chapter 4 of the tutorial we will explore some extremely 
+helpful and powerful features of L<DBIx::Class> that allow you to pull 
+code out of your views and controllers and place it where it 
+rightfully belongs in a model class.
 
 
 =head2 Test Run The Application
 
 To test your work so far, first start the development server:
 
-    $ script/myapp_server.pl
+    $ script/myapp_server.pl -r
 
 Then point your browser to L<http://localhost:3000> and you should
 still get the Catalyst welcome page.  Next, change the URL in your
@@ -561,13 +564,15 @@ 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.  We will use SQLite,
-a popular database that is lightweight and easy to use.  Open
+create a database table and load some sample data.  We will use 
+SQLite (L<http://www.sqlite.org>), a popular database that is
+lightweight and easy to use. Be sure to get at least version 3. Open
 C<myapp01.sql> in your editor and enter:
 
     --
     -- Create a very simple database to hold book and author information
     --
+    PRAGMA foreign_keys = ON;
     CREATE TABLE book (
             id          INTEGER PRIMARY KEY,
             title       TEXT ,
@@ -575,8 +580,8 @@ C<myapp01.sql> in your editor and enter:
     );
     -- 'book_author' is a many-to-many join table between books & authors
     CREATE TABLE book_author (
-            book_id     INTEGER,
-            author_id   INTEGER,
+            book_id     INTEGER REFERENCES book(id) ON DELETE CASCADE ON UPDATE CASCADE,
+            author_id   INTEGER REFERENCES author(id) ON DELETE CASCADE ON UPDATE CASCADE,
             PRIMARY KEY (book_id, author_id)
     );
     CREATE TABLE author (
@@ -622,8 +627,9 @@ can use the SQLite command line environment to do a quick dump of the
 database contents:
 
     $ sqlite3 myapp.db
-    SQLite version 3.5.9
+    SQLite version 3.6.22
     Enter ".help" for instructions
+    Enter SQL statements terminated with a ";"
     sqlite> select * from book;
     1|CCSP SNRS Exam Certification Guide|5
     2|TCP/IP Illustrated, Volume 1|5
@@ -648,14 +654,14 @@ 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.
 
-Please note that here we have chosen to use 'singular' table names. This
-is because the default inflection code for L<DBIx::Class:Schema::Loader>
-does NOT handle plurals. There has been much philosophical discussion
-on whether table names should be plural or singular. There is no one
-correct answer, as long as one makes a choice and remains consistent
-with it. If you prefer plural table names (e.g. they are easier and
-more natural to read) then you will need to pass it an inflect_map 
-option. See L<DBIx::Class:Schema::Loader> for more information.
+Please note that here we have chosen to use 'singular' table names. This is
+because the default inflection code for older versions of
+L<DBIx::Class::Schema::Loader> does NOT handle plurals. There has been much
+philosophical discussion on whether table names should be plural or singular.
+There is no one correct answer, as long as one makes a choice and remains
+consistent with it. If you prefer plural table names (e.g. you think that they
+are easier to read) then see the documentation in
+L<DBIx::Class::Schema::Loader::Base/naming> (version 0.05 or greater).
 
 For using other databases, such as PostgreSQL or MySQL, see 
 L<Appendix 2|Catalyst::Manual::Tutorial::10_Appendices>.
@@ -665,7 +671,7 @@ L<Appendix 2|Catalyst::Manual::Tutorial::10_Appendices>.
 
 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> 
+can be used to access databases through the traditional Perl L<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 
@@ -686,24 +692,34 @@ 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:
+L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema>, so
+that we can take advantage of some recent enhancements in how
+foreign keys are handled with SQLite.  To check your version, 
+run this command:
 
     $ perl -MCatalyst::Model::DBIC::Schema -e \
         'print "$Catalyst::Model::DBIC::Schema::VERSION\n"'
-    0.23
+    0.39
 
 Please note the '\' above.  Depending on your environment, you might 
 be able to cut and paste the text as shown or need to remove the '\' 
 character to that the command is all on a single line.
 
-If you don't have version 0.23 or higher, please run this command
-to install it directly from CPAN:
+If you have less than v0.39, you will need to 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.
+0.39 or higher.
+
+In addition, since we are using SQLite's foreign key support here,
+please be sure that you use version C<1.27> of L<DBD::SQLite> or later:
+
+    $ perl -MDBD::SQLite -e 'print "$DBD::SQLite::VERSION\n"'
+    1.29
+
+Upgrade if you are not at version C<1.27> or higher.
 
 
 =head2 Create Static DBIx::Class Schema Files
@@ -715,7 +731,8 @@ 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 dbi:SQLite:myapp.db
+        create=static dbi:SQLite:myapp.db \
+        on_connect_do="PRAGMA foreign_keys = ON"
      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 ...
@@ -754,13 +771,20 @@ into files.
 
 =item *
 
-C<components=TimeStamp> causes the help to include the 
-L<DBIx::Class::TimeStamp|DBIx::Class::TimeStamp> DBIC component.
+C<dbi:SQLite:myapp.db> is the standard DBI connect string 
+for use with SQLite.
 
 =item *
 
-And finally, C<dbi:SQLite:myapp.db> is the standard DBI connect string 
-for use with SQLite.
+And finally, the C<on_connect_do> string requests that 
+L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> create 
+foreign key relationships for us (this is not needed for databases such 
+as PostgreSQL and MySQL, but is required for SQLite). If you take a look 
+at C<lib/MyApp/Model/DB.pm>, you will see that the SQLite pragma is 
+propogated to the Model, so that SQLite's recent (and optional) foreign 
+key enforcement is enabled at the start of every database connection. 
+
+
 
 =back
 
@@ -801,31 +825,15 @@ 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):
+use this process to automate the migration, but first make sure you have
+version C<0.39> of L<Catalyst::Model::DBIC::Schema> and
+L<DBIx::Class::Schema::Loader> version C<0.05000> or later.
 
-    $ # 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"
+    $ # Re-run the helper to upgrade for you
     $ script/myapp_create.pl model DB DBIC::Schema MyApp::Schema \
-        create=static 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
-
-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).
+        create=static naming=current use_namespaces=1 \
+        dbi:SQLite:myapp.db \
+        on_connect_do="PRAGMA foreign_keys = ON"
 
 
 =head1 ENABLE THE MODEL IN THE CONTROLLER
@@ -841,20 +849,20 @@ and delete the next 2 lines):
     
     =cut
     
-    sub list : Local {
+    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
+        # 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::Book')->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';
+        $c->stash(template => 'books/list.tt2');
     }
 
 B<TIP>: You may see the C<$c-E<gt>model('DB::Book')> un-commented 
@@ -884,10 +892,12 @@ and L<Catalyst::Model::DBIC::Schema|Catalyst::Model::DBIC::Schema>.
 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:
+code.  Press C<Ctrl-C> to break out of the development server and
+enter:
 
     $ export DBIC_TRACE=1
-
+    $ script/myapp_server.pl -r 
+    
 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>).
@@ -901,14 +911,13 @@ log).
 Then launch the Catalyst development server.  The log output should
 display something like:
 
-    $ script/myapp_server.pl
+    $ script/myapp_server.pl -r
     [debug] Debug messages enabled
     [debug] Statistics enabled
     [debug] Loaded plugins:
     .----------------------------------------------------------------------------.
-    | Catalyst::Plugin::ConfigLoader  0.22                                       |
-    | Catalyst::Plugin::StackTrace  0.09                                         |
-    | Catalyst::Plugin::Static::Simple  0.21                                     |
+    | Catalyst::Plugin::ConfigLoader  0.27                                       |
+    | Catalyst::Plugin::StackTrace  0.11                                         |
     '----------------------------------------------------------------------------'
     
     [debug] Loaded dispatcher "Catalyst::Dispatcher"
@@ -949,7 +958,7 @@ display something like:
     | /books/list                         | /books/list                          |
     '-------------------------------------+--------------------------------------'
     
-    [info] MyApp powered by Catalyst 5.80003
+    [info] MyApp powered by Catalyst 5.80020
     You can connect to your server at http://debian:3000
 
 B<NOTE:> Be sure you run the C<script/myapp_server.pl> command from
@@ -1010,10 +1019,10 @@ edit many individual files.
 =head2 Configure TT.pm For The Wrapper
 
 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>.
+tell it where to find your wrapper file. 
 
-Edit C<lib/MyApp/View/TT.pm> and change it to match the following:
+Edit you TT view in C<lib/MyApp/View/TT.pm> and change it to match the 
+following:
 
     __PACKAGE__->config(
         # Change default TT extension
@@ -1162,35 +1171,128 @@ 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.
+Hit "Reload" in your web browser and you should now see a formatted 
+version of our basic book list. (Again, the development server should 
+have automatically restarted when you made changes to 
+C<lib/MyApp/View/TT.pm>. If you are not using the "-r" option, you will 
+need to hit C<Ctrl-C> and manually restart it. Also note that the 
+development server does I<NOT> need to restart for changes to the TT and 
+static files we created and edited in the C<root> directory -- those 
+updates are handled on a per-request basis.) 
+
+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/Book.pm> and add the 
-following text below the C<# You can replace this text...> comment:
+If you take a look at the Schema files automatically generated by 
+L<DBIx::Class::Schema::Loader>, you will see that it has already defined 
+C<has_many> and C<belongs_to> relationships on each side of our foreign 
+keys. For example, take a look at C<lib/MyApp/Schema/Result/Book.pm> and 
+notice the following code: 
 
-    #
-    # 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 (aka, foreign key in peer table)
-    __PACKAGE__->has_many(book_authors => 'MyApp::Schema::Result::BookAuthor', 'book_id');
+    =head1 RELATIONS
+
+    =head2 book_authors
+
+    Type: has_many
+
+    Related object: L<MyApp::Schema::Result::BookAuthor>
+
+    =cut
+
+    __PACKAGE__->has_many(
+      "book_authors",
+      "MyApp::Schema::Result::BookAuthor",
+      { "foreign.book_id" => "self.id" },
+    );
+
+Each C<Book> "has_many" C<book_authors>, where C<BookAuthor> is
+the many-to-many table that allows each Book to have multiple
+Authors, and each Author to have mulitple books.  The arguments
+to C<has_many> are:
+
+=over 4
+
+=item *
+
+C<book_authors> - The name for this relationship.  DBIC will create
+an accessor on the C<Books> DBIC Row object with this name.
+
+=item *
+
+C<MyApp::Schema::Result::BookAuthor> - The name of the DBIC model
+class referenced by this C<has_many> relationship.
+
+=item *
+
+C<foreign.book_id> - C<book_id> is the name of the foreign key 
+column in the I<foreign> table that points back to this table.
+
+=item *
+
+C<self.id> - C<id> is the name of the column in I<this> table
+that is referenced by the foreign key.
+
+=back
+
+See L<DBIx::Class::Relationship/has_many> for
+additional information.  Note that you might see a "hand coded"
+version of the C<has_many> relationship above expressed as:
+
+    __PACKAGE__->has_many(
+      "book_authors",
+      "MyApp::Schema::Result::BookAuthor",
+      "book_id",
+    );
+
+Where the third argument is simply the name of the column in
+the foreign table.  However, the hashref syntax used by 
+L<DBIx::Class::Schema::Loader> is more flexible (for example,
+it can handle "multi-column" foreign keys).
+
+B<Note:> If you are using older versions of SQLite and related DBIC 
+tools, you will need to manually define your C<has_many> and 
+C<belongs_to> relationships. We recommend upgrading to the versions 
+specified above. :-) 
+
+Have a look at C<lib/MyApp/Schema/Result/BookAuthor.pm> and notice
+that there is a C<belongs_to> relationship defined that acts as the
+"mirror image" to the C<has_many> relationship we just looked at
+above:
+
+    =head1 RELATIONS
+
+    =head2 book
+
+    Type: belongs_to
+
+    Related object: L<MyApp::Schema::Result::Book>
+
+    =cut
+
+    __PACKAGE__->belongs_to(
+      "book",
+      "MyApp::Schema::Result::Book",
+      { id => "book_id" },
+      { join_type => "LEFT" },
+    );
+
+
+The arguments are similar, but see 
+L<DBIx::Class::Relationship/belongs_to> for the details.
     
+Although recent versions of SQLite and L<DBIx::Class::Schema::Loader> 
+automatically handle the C<has_many> and C<belongs_to> relationships, 
+C<many_to_many> relationships currently need to be manually inserted. 
+To add a C<many_to_many> relationship, first edit 
+C<lib/MyApp/Schema/Result/Book.pm> and add the following text below 
+the C<# You can replace this text...> comment:
+
     # many_to_many():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
@@ -1199,40 +1301,28 @@ following text below the C<# You can replace this text...> comment:
     #   You must already have the has_many() defined to use a many_to_many().
     __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
 
-
 B<Note:> Be careful to put this code I<above> the C<1;> at the end of the
 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 
+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_author> table as in 
 C<$book-E<gt>book_author-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_author> 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>author-
-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/Author.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):
-
-    #
-    # Set relationships:
-    #
-    
-    # has_many():
-    #   args:
-    #     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 (aka, foreign key in peer table)
-    __PACKAGE__->has_many(book_authors => 'MyApp::Schema::Result::BookAuthor', 'author_id');
-    
+C<many_to_many> allows us to use the shorter 
+C<$book-E<gt>author-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/Author.pm> and add the reverse 
+C<many_to_many> relationship for C<Author> as follows (again, be careful 
+to put in above the C<1;> but below the C<# DO NOT MODIFY THIS OR 
+ANYTHING ABOVE!> comment): 
+
     # many_to_many():
     #   args:
     #     1) Name of relationship, DBIC will create accessor with this name
@@ -1241,27 +1331,6 @@ below the C<# DO NOT MODIFY THIS OR ANYTHING ABOVE!> comment):
     #   You must already have the has_many() defined to use a many_to_many().
     __PACKAGE__->many_to_many(books => 'book_authors', 'book');
 
-Finally, do the same for the "join table,"
-C<lib/MyApp/Schema/Result/BookAuthor.pm>:
-
-    #
-    # Set relationships:
-    #
-    
-    # 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(book => 'MyApp::Schema::Result::Book', '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::Result::Author', 'author_id');
-
 
 =head2 Run The Application
 
@@ -1269,16 +1338,15 @@ 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
+    $ DBIC_TRACE=1 script/myapp_server.pl -r
 
 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> 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.
+and be sure that the book list still displays correctly. You can leave 
+the development server running for the next step if you wish.
 
 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 
@@ -1297,11 +1365,11 @@ the "empty" table cell "<td></td>" with the following:
       [% # NOTE: See Chapter 4 for a better way to do this!                      -%]
       [% # 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 the 'push' TT vmethod does not print -%]
+      [% # authors into the list. Note that the 'push' TT vmethod doesn't return -%]
       [% # a value, so nothing will be printed here.  But, if you have something -%]
-      [% # in TT that does return a method and you don't want it printed, you    -%]
-      [% # can: 1) assign it to a bogus value, or 2) use the CALL keyword to     -%]
-      [% # call it and discard the return value.                                 -%]
+      [% # in TT that does return a value and you don't want it printed, you     -%]
+      [% # 1) assign it to a bogus value, or                                     -%]
+      [% # 2) use the CALL keyword to call it and discard the return value.      -%]
       [% tt_authors = [ ];
          tt_authors.push(author.last_name) FOREACH author = book.authors %]
       [% # Now use a TT 'virtual method' to display the author count in parens   -%]
@@ -1312,13 +1380,13 @@ the "empty" table cell "<td></td>" with the following:
     </td>
     ...
 
-B<IMPORTANT NOTE:> You should keep as much "logic code" as possible 
-out of your views.  Instead, this kind of logic belongs in your model 
+B<IMPORTANT NOTE:> Again, you should keep as much "logic code" as 
+possible out of your views.  This kind of logic belongs in your model 
 (the same goes for controllers -- keep them as "thin" as possible and 
 push all of the "complicated code" out to your model objects).  Avoid 
 code like you see in the previous example -- we are only using it here 
 to show some extra features in TT until we get to the more advanced 
-model features we will see in Chapter 4 (see
+model features we will see in Chapter 4 (see 
 L<Catalyst::Manual::Tutorial::04_BasicCRUD/EXPLORING THE POWER OF DBIC>).
 
 Then hit "Reload" in your browser (note that you don't need to reload 
@@ -1479,7 +1547,7 @@ has changed):
     
     =cut
     
-    sub list : Local {
+    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
@@ -1492,7 +1560,7 @@ has changed):
         # Set the TT template to use.  You will almost always want to do this
         # in your action methods (actions methods respond to user input in
         # your controllers).
-        #$c->stash->{template} = 'books/list.tt2';
+        #$c->stash(template => 'books/list.tt2');
     }