Moving tutorial POD here
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Tutorial / Tutorial / CatalystBasics.pod
diff --git a/lib/Catalyst/Manual/Tutorial/Tutorial/CatalystBasics.pod b/lib/Catalyst/Manual/Tutorial/Tutorial/CatalystBasics.pod
new file mode 100644 (file)
index 0000000..cfa1439
--- /dev/null
@@ -0,0 +1,1242 @@
+=head1 NAME
+
+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.
+
+L<Tutorial Overview|Catalyst::Manual::Tutorial>
+
+=over 4
+
+=item 1
+
+L<Introduction|Catalyst::Manual::Tutorial::Intro>
+
+=item 2
+
+B<Catalyst Basics>
+
+=item 3
+
+L<Basic CRUD|Catalyst::Manual::Tutorial::BasicCRUD>
+
+=item 4
+
+L<Authentication|Catalyst::Manual::Tutorial::Authentication>
+
+=item 5
+
+L<Authorization|Catalyst::Manual::Tutorial::Authorization>
+
+=item 6
+
+L<Debugging|Catalyst::Manual::Tutorial::Debugging>
+
+=item 7
+
+L<Testing|Catalyst::Manual::Tutorial::Testing>
+
+=item 8
+
+L<Advanced CRUD|Catalyst::Manual::Tutorial::AdvancedCRUD>
+
+=item 9
+
+L<Appendices|Catalyst::Manual::Tutorial::Appendices>
+
+=back
+
+
+=head1 DESCRIPTION
+
+In this part of the tutorial, we will create a very basic Catalyst web
+application.  Though simple in many respects, this section will already
+demonstrate a number of powerful capabilities such as:
+
+=over 4
+
+=item * Helper Scripts
+
+Catalyst helper scripts that can be used to rapidly bootstrap the
+skeletal structure of an application.
+
+=item * MVC
+
+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
+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>. In short:
+
+=over 4
+
+=item * Model
+
+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
+creates HTML for the user's web browser, but it could easily be code
+that generates other forms such as PDF documents, e-mails, or Excel
+spreadsheets.
+
+=item * Controller
+
+As suggested by its name, the controller takes user requests and routes
+them to the necessary model and view.
+
+=back
+
+=item * ORM
+
+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
+
+You can checkout the source code for this example from the catalyst
+subversion repository as per the instructions in
+L<Catalyst::Manual::Tutorial::Intro>
+
+=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 (see L<Catalyst::Helper|Catalyst::Helper>
+for more information on helpers).  Also note that as of Catalyst 5.7000,
+you will not have the helper scripts unless you install both 
+L<Catalyst::Runtime|Catalyst::Runtime> and L<Catalyst::Devel|Catalyst::Devel>.
+
+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 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
+    [debug] Debug messages enabled
+    [debug] Loaded plugins:
+    .----------------------------------------------------------------------------.
+    | Catalyst::Plugin::ConfigLoader  0.13                                       |
+    | 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 Config "/home/me/myapp.yml"
+    [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.7002
+    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.  It doesn't make a difference at this point, but it will as soon
+as we get the database going in the next section.
+
+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:
+
+    [info] *** Request 1 (0.043/s) [6003] [Fri Jul  7 13:32:53 2006] ***
+    [debug] "GET" request for "/" from "127.0.0.1"
+    [info] Request took 0.067675s (14.777/s)
+    .----------------------------------------------------------------+-----------.
+    | Action                                                         | Time      |
+    +----------------------------------------------------------------+-----------+
+    | /default                                                       | 0.002844s |
+    | /end                                                           | 0.000207s |
+    '----------------------------------------------------------------+-----------'
+
+Press Ctrl-C to break out of the development server.
+
+
+=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 very simple database to hold book and author information
+    --
+    CREATE TABLE books (
+            id          INTEGER PRIMARY KEY,
+            title       TEXT ,
+            rating      INTEGER
+    );
+    -- 'book_authors' is a many-to-many join table between books & authors
+    CREATE TABLE book_authors (
+            book_id     INTEGER,
+            author_id   INTEGER,
+            PRIMARY KEY (book_id, author_id)
+    );
+    CREATE TABLE authors (
+            id          INTEGER PRIMARY KEY,
+            first_name  TEXT,
+            last_name   TEXT
+    );
+    ---
+    --- Load some sample data
+    ---
+    INSERT INTO books VALUES (1, 'CCSP SNRS Exam Certification Guide', 5);
+    INSERT INTO books VALUES (2, 'TCP/IP Illustrated, Volume 1', 5);
+    INSERT INTO books VALUES (3, 'Internetworking with TCP/IP Vol.1', 4);
+    INSERT INTO books VALUES (4, 'Perl Cookbook', 5);
+    INSERT INTO books VALUES (5, 'Designing with Web Standards', 5);
+    INSERT INTO authors VALUES (1, 'Greg', 'Bastien');
+    INSERT INTO authors VALUES (2, 'Sara', 'Nasseh');
+    INSERT INTO authors VALUES (3, 'Christian', 'Degu');
+    INSERT INTO authors VALUES (4, 'Richard', 'Stevens');
+    INSERT INTO authors VALUES (5, 'Douglas', 'Comer');
+    INSERT INTO authors VALUES (6, 'Tom', 'Christiansen');
+    INSERT INTO authors VALUES (7, 'Nathan', 'Torkington');
+    INSERT INTO authors VALUES (8, 'Jeffrey', 'Zeldman');
+    INSERT INTO book_authors VALUES (1, 1);
+    INSERT INTO book_authors VALUES (1, 2);
+    INSERT INTO book_authors VALUES (1, 3);
+    INSERT INTO book_authors VALUES (2, 4);
+    INSERT INTO book_authors VALUES (3, 5);
+    INSERT INTO book_authors VALUES (4, 6);
+    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.
+
+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.2.2
+    Enter ".help" for instructions
+    sqlite> select * from books;
+    1|CCSP SNRS Exam Certification Guide|5
+    2|TCP/IP Illustrated, Volume 1|5
+    3|Internetworking with TCP/IP Vol.1|4
+    4|Perl Cookbook|5
+    5|Designing with Web Standards|5
+    sqlite> .q
+    $
+
+Or:
+
+    $ sqlite3 myapp.db "select * from books"
+    1|CCSP SNRS Exam Certification Guide|5
+    2|TCP/IP Illustrated, Volume 1|5
+    3|Internetworking with TCP/IP Vol.1|4
+    4|Perl Cookbook|5
+    5|Designing with Web Standards|5
+
+As with most other SQL tools, if you are using the full "interactive"
+environment you need to terminate your SQL commands with a ";" (it's not
+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.
+
+
+=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.
+
+By default, Catalyst enables three plugins/flags:
+
+=over 4
+
+=item * 
+
+C<-Debug> Flag
+
+Enables the Catalyst debug output you saw when we started the
+C<script/myapp_server.pl> development server earlier.  You can remove
+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).  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.
+
+=item *
+
+L<Catalyst::Plugin::ConfigLoader|Catalyst::Plugin::ConfigLoader>
+
+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
+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>
+
+C<Static::Simple> provides an easy method of serving static content such
+as images and CSS files under 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:
+
+    use Catalyst qw/-Debug ConfigLoader Static::Simple/;
+
+Replace it with:
+
+    use Catalyst qw/
+            -Debug
+            ConfigLoader
+            Static::Simple
+            
+            StackTrace
+            /;
+
+This tells Catalyst to start using one new plugin:
+
+=over 4
+
+=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<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
+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.7000, 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.7000 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 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> 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>).  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.
+
+Create C<lib/MyAppDB.pm> in your editor and insert:
+
+    package MyAppDB;
+    
+    =head1 NAME 
+    
+    MyAppDB - DBIC Schema Class
+    
+    =cut
+    
+    # Our schema needs to inherit from 'DBIx::Class::Schema'
+    use base qw/DBIx::Class::Schema/;
+    
+    # Need to load the DB Model classes here.
+    # You can use this syntax if you want:
+    #    __PACKAGE__->load_classes(qw/Book BookAuthor Author/);
+    # Also, if you simply want to load all of the classes in a directory
+    # of the same name as your schema class (as we do here) you can use:
+    #    __PACKAGE__->load_classes(qw//);
+    # But the variation below is more flexible in that it can be used to 
+    # load from multiple namespaces.
+    __PACKAGE__->load_classes({
+        MyAppDB => [qw/Book BookAuthor Author/]
+    });
+    
+    1;
+
+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>.
+
+B<Note:> 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 as shown above.
+
+
+=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 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:
+
+    $ mkdir lib/MyAppDB
+
+Then create C<lib/MyAppDB/Book.pm> in your editor and enter:
+
+    package MyAppDB::Book;
+    
+    use base qw/DBIx::Class/;  
+    
+    # Load required DBIC stuff
+    __PACKAGE__->load_components(qw/PK::Auto Core/);
+    # Set the table name
+    __PACKAGE__->table('books');
+    # Set columns in table
+    __PACKAGE__->add_columns(qw/id title rating/);
+    # Set the primary key for the table
+    __PACKAGE__->set_primary_key(qw/id/);
+    
+    #
+    # 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 => 'MyAppDB::BookAuthor', '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 
+    #   You must already have the has_many() defined to use a many_to_many().
+    __PACKAGE__->many_to_many(authors => 'book_authors', 'author');
+    
+    
+    =head1 NAME
+    
+    MyAppDB::Book - A model object representing a book.
+    
+    =head1 DESCRIPTION
+    
+    This is an object that represents a row in the 'books' table of your application
+    database.  It uses DBIx::Class (aka, DBIC) to do ORM.
+    
+    For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
+    Offline utilities may wish to use this class directly.
+    
+    =cut
+    
+    1;
+
+This 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.
+
+Next, create C<lib/MyAppDB/Author.pm> in your editor and enter:
+
+    package MyAppDB::Author;
+    
+    use base qw/DBIx::Class/;
+    
+    # Load required DBIC stuff
+    __PACKAGE__->load_components(qw/PK::Auto Core/);
+    # Set the table name
+    __PACKAGE__->table('authors');
+    # Set columns in table
+    __PACKAGE__->add_columns(qw/id first_name last_name/);
+    # Set the primary key for the table
+    __PACKAGE__->set_primary_key(qw/id/);
+    
+    #
+    # 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_author => 'MyAppDB::BookAuthor', '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 
+    #   You must already have the has_many() defined to use a many_to_many().
+    __PACKAGE__->many_to_many(books => 'book_author', 'book');
+    
+    
+    =head1 NAME
+    
+    MyAppDB::Author - A model object representing an author of a book (if a book has 
+    multiple authors, each will be represented be separate Author object).
+    
+    =head1 DESCRIPTION
+    
+    This is an object that represents a row in the 'authors' table of your application
+    database.  It uses DBIx::Class (aka, DBIC) to do ORM.
+    
+    For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
+    Offline utilities may wish to use this class directly.
+    
+    =cut
+    
+    1;
+
+Finally, create C<lib/MyAppDB/BookAuthor.pm> in your editor and enter:
+
+    package MyAppDB::BookAuthor;
+    
+    use base qw/DBIx::Class/;
+    
+    # Load required DBIC stuff
+    __PACKAGE__->load_components(qw/PK::Auto Core/);
+    # Set the table name
+    __PACKAGE__->table('book_authors');
+    # Set columns in table
+    __PACKAGE__->add_columns(qw/book_id author_id/);
+    # Set the primary key for the table
+    __PACKAGE__->set_primary_key(qw/book_id author_id/);
+    
+    #
+    # 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 => 'MyAppDB::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 => 'MyAppDB::Author', 'author_id');
+    
+    
+    =head1 NAME
+    
+    MyAppDB::BookAuthor - A model object representing the JOIN between an author and 
+    a book.
+    
+    =head1 DESCRIPTION
+    
+    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.
+    
+    For Catalyst, this is designed to be used through MyApp::Model::MyAppDB.
+    Offline utilities may wish to use this class directly.
+    
+    =cut
+    
+    1;
+
+B<Note:> This sample application uses a plural form for the database
+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
+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 
+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:
+
+    $ 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
+existing schema file we created (in C<lib/MyAppDB.pm>).  You can see
+that the helper creates a model file under 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> [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 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:
+
+    $ 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:
+
+    =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('MyAppDB::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';
+    }
+
+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('MyAppDB::Book')> used above
+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 (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, 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:
+
+=over 4
+
+=item *
+
+L<Catalyst::Helper::View::TT|Catalyst::Helper::View::TT>
+
+=item *
+
+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>
+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). 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 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
+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>. 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
+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<lib/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).
+
+B<NOTE:> 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 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.7000 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 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 
+the attribute 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 than 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
+
+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>
+
+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.
+
+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).
+
+
+=head2 Create a TT Template Page
+
+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.
+
+First create a directory for book-related TT templates:
+
+    $ mkdir root/src/books
+
+Then create C<root/src/books/list.tt2> in your editor and enter:
+
+    [% # This is a TT comment.  The '-' at the end "chomps" the newline.  You won't -%]
+    [% # see this "chomping" in your browser because HTML ignores blank lines, but  -%]
+    [% # 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 -%]
+    [% META title = 'Book List' -%]
+    
+    <table>
+    <tr><th>Title</th><th>Rating</th><th>Author(s)</th></tr>
+    [% # Display each book in a table row %]
+    [% FOREACH book IN books -%]
+      <tr>
+        <td>[% book.title %]</td>
+        <td>[% book.rating %]</td>
+        <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     -%]
+          [% # authors into the list.  Note that the 'push' TT vmethod does not      -%]
+          [% # 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.                                 -%]
+          [% 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   -%]
+          ([% tt_authors.size %])
+          [% # Use another TT vmethod to join & print the names & comma separators   -%]
+          [% tt_authors.join(', ') %]
+        </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 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 comma-separated
+list within a single table cell.
+
+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://www.template-toolkit.org/docs/default/Manual/Variables.html>
+for details and examples).  In addition to the usual C<Template> module
+Pod documentation, you can access the TT manual at
+L<http://www.template-toolkit.org/docs/default/>.
+
+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.
+
+
+=head1 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):
+
+    $ export DBIC_TRACE=1
+
+B<NOTE>: You can also use the older 
+C<export DBIX_CLASS_STORAGE_DBI_DEBUG=1>, but that's a lot more to
+type.
+
+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> 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
+
+Your development server log output should display something like:
+
+    $ script/myapp_server.pl
+    [debug] Debug messages enabled
+    [debug] Loaded plugins:
+    .----------------------------------------------------------------------------.
+    | Catalyst::Plugin::ConfigLoader  0.13                                       |
+    | Catalyst::Plugin::StackTrace  0.06                                         |
+    | 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 Config "/home/me/myapp.yml"
+    [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.7002
+    You can connect to your server at http://localhost:3000
+
+Some things you should note in the output above:
+
+=over 4
+
+=item * 
+
+Catalyst::Model::DBIC::Schema took our C<MyAppDB::Book> and made it
+C<MyApp::Model::MyAppDB::Book> (and similar actions were performed on
+C<MyAppDB::Author> and C<MyAppDB::BookAuthor>).
+
+=item * 
+
+The "list" action in our Books controller showed up with a path of
+C</books/list>.
+
+=back
+
+Point your browser to L<http://localhost:3000> and you should still get
+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 count and space-separated list of author last names appear on the
+end of each row.
+
+Also notice in the output of the C<script/myapp_server.pl> that DBIC
+used the following SQL to retrieve the data:
+
+    SELECT me.id, me.title, me.rating FROM books me
+
+Along with a list of the following commands to retrieve the authors for
+each book (the lines have been "word wrapped" here to improve
+legibility):
+
+    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'
+
+You should see 5 such lines of debug output as DBIC fetches the author 
+information for each book.
+
+
+=head1 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 
+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):
+
+    =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('MyAppDB::Book')->all];
+    
+        # 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<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 
+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 8 of the Tutorial).
+
+
+=head1 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
+statement in C<sub list>:
+
+    $c->stash->{template} = 'books/list.tt2';
+
+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 
+access L<http://localhost:3000/books/list> in the same manner as
+with earlier sections.
+
+
+=head1 AUTHOR
+
+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-Runtime/lib/Catalyst/Manual/Tutorial/>.
+
+Copyright 2006, Kennedy Clark, under Creative Commons License
+(L<http://creativecommons.org/licenses/by-nc-sa/2.5/>).
+