Intro.pod patch from blblack
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Intro.pod
index 8e0211c..632e1c3 100644 (file)
@@ -8,12 +8,23 @@ This is a brief introduction to Catalyst. It explains the most important
 features of how Catalyst works and shows how to get a simple application
 up and running quickly. For an introduction (without code) to Catalyst
 itself, and why you should be using it, see L<Catalyst::Manual::About>.
+For a systematic step-by-step introduction to writing an application
+with Catalyst, see L<Catalyst::Manual::Tutorial>.
 
 =head2 What is Catalyst?
 
-Catalyst is an elegant web application framework, extremely flexible yet
-extremely simple. It's similar to Ruby on Rails, Spring (Java), and
-L<Maypole>, upon which it was originally based.
+Catalyst is an elegant web application framework, extremely flexible
+yet extremely simple. It's similar to Ruby on Rails, Spring (Java),
+and L<Maypole>, upon which it was originally based. Its most important
+design philosphy is to provide easy access to all the tools you need
+to develop web applications, with few restrictions on how you need to
+use these tools. However, this does mean that it is always possible to
+do things in a different way. Other web frameworks are B<initially>
+simpler to use, but achieve this by locking the programmer into a
+single set of tools. Catalyst's emphasis on flexibility means that you
+have to think more to use it. We view this as a feature.  For example,
+this leads to Catalyst being more suited to system integration tasks
+than other web frameworks.
 
 =head3 MVC
 
@@ -24,15 +35,15 @@ modify code that handles one concern without affecting code that handles
 the others. Catalyst promotes the re-use of existing Perl modules that
 already handle common web application concerns well.
 
-Here's how the M, V, and C map to those concerns, with examples of
-well-known Perl modules you may want to use for each.
+Here's how the Model, View, and Controller map to those concerns, with
+examples of well-known Perl modules you may want to use for each.
 
 =over 4
 
 =item * B<Model>
 
 Access and modify content (data). L<DBIx::Class>, L<Class::DBI>,
-L<Plucene>, L<Net::LDAP>...
+L<Xapian>, L<Net::LDAP>...
 
 =item * B<View>
 
@@ -46,17 +57,16 @@ control. Catalyst itself!
 
 =back
 
-If you're unfamiliar with MVC and design patterns, you may want to check
-out the original book on the subject, I<Design Patterns>, by Gamma,
-Helm, Johnson, and Vlissides, also known as the Gang of Four (GoF).
-Many, many web application frameworks are based on MVC, including all
-those listed above.
+If you're unfamiliar with MVC and design patterns, you may want to
+check out the original book on the subject, I<Design Patterns>, by
+Gamma, Helm, Johnson, and Vlissides, also known as the Gang of Four
+(GoF).  Many, many web application frameworks are based on MVC, which
+is becoming a popular design paradigm for the world wide web.
 
 =head3 Flexibility
 
-Catalyst is much more flexible than many other frameworks. We'll talk
-more about this later, but rest assured you can use your favorite Perl
-modules with Catalyst.
+Catalyst is much more flexible than many other frameworks. Rest assured
+you can use your favorite Perl modules with Catalyst.
 
 =over 4
 
@@ -94,9 +104,10 @@ example:
 
 Now http://localhost:3000/hello prints "Hello World!".
 
-=item * B<Support for CGI, mod_perl, Apache::Request>
+=item * B<Support for CGI, mod_perl, Apache::Request, FastCGI>
 
-Use L<Catalyst::Engine::Apache> or L<Catalyst::Engine::CGI>.
+Use L<Catalyst::Engine::Apache> or L<Catalyst::Engine::CGI>. Other
+engines are also available.
 
 =back
 
@@ -129,12 +140,14 @@ L<Catalyst::View::TT> for L<Template Toolkit|Template>.
 =item * B<Built-in Test Framework>
 
 Catalyst comes with a built-in, lightweight http server and test
-framework, making it easy to test applications from the command line.
+framework, making it easy to test applications from the web browser,
+and the command line.
 
 =item * B<Helper Scripts>
 
 Catalyst provides helper scripts to quickly generate running starter
-code for components and unit tests. See L<Catalyst::Helper>.
+code for components and unit tests. Install L<Catalyst::Devel> and see
+L<Catalyst::Helper>.
 
 =back
 
@@ -145,7 +158,14 @@ running, using the helper scripts described above.
 
 =head3 Install
 
-    $ perl -MCPAN -e 'install Task::Catalyst'
+Installation of Catalyst can be a time-consuming and frustrating
+effort, due to its large number of dependencies. The easiest way
+to get up and running is to use Matt Trout's C<cat-install>
+script, from L<http://www.shadowcatsystems.co.uk/static/cat-install>,
+and then install L<Catalyst::Devel>.
+
+    # perl cat-install
+    # perl -MCPAN -e 'install Catalyst::Devel'
 
 =head3 Setup
 
@@ -173,24 +193,364 @@ Both of these URLs should take you to the welcome page.)
 
 =back
 
-Easy!
-
 =head2 How It Works
 
 Let's see how Catalyst works, by taking a closer look at the components
 and other parts of a Catalyst application.
 
+=head3 Components
+
+Catalyst has an uncommonly flexible component system. You can define as
+many L</Models>, L</Views>, and L</Controllers> as you like. As discussed
+previously, the general idea is that the View is responsible for the
+output of data to the user (typically via a web browser, but a View can
+also generate PDFs or e-mails, for example); the Model is responsible 
+for providing data (typically from a relational database); and the
+Controller is responsible for interacting with the user and deciding
+how user input determines what actions the application takes.
+
+In the world of MVC, there are frequent discussions and disagreements
+about the nature of each element - whether certain types of logic
+belong in the Model or the Controller, etc. Catalyst's flexibility
+means that this decision is entirely up to you, the programmer; 
+Catalyst doesn't enforce anything. See L<Catalyst::Manual::About> for
+a general discussion of these issues.
+
+All components must inherit from L<Catalyst::Base>, which provides a
+simple class structure and some common class methods like C<config> and
+C<new> (constructor).
+
+    package MyApp::Controller::Catalog;
+
+    use strict;
+    use base 'Catalyst::Base';
+
+    __PACKAGE__->config( foo => 'bar' );
+
+    1;
+
+You don't have to C<use> or otherwise register Models, Views, and
+Controllers.  Catalyst automatically discovers and instantiates them
+when you call C<setup> in the main application. All you need to do is
+put them in directories named for each Component type. You can use a
+short alias for each one.
+
+=over 4
+
+=item * B<MyApp/Model/> 
+
+=item * B<MyApp/M/>
+
+=item * B<MyApp/View/>
+
+=item * B<MyApp/V/>
+
+=item * B<MyApp/Controller/>
+
+=item * B<MyApp/C/>
+
+=back
+
+In older versions of Catalyst, the recommended practice (and the one
+automatically created by helper scripts) was to name the directories
+C<M/>, C<V/>, and C<C/>. Though these still work, we now recommend
+the use of the full names.
+
+=head4 Views
+
+To show how to define views, we'll use an already-existing base class for the
+L<Template Toolkit|Template>, L<Catalyst::View::TT>. All we need to do is
+inherit from this class:
+
+    package MyApp::View::TT;
+
+    use strict;
+    use base 'Catalyst::View::TT';
+
+    1;
+
+(You can also generate this automatically by using the helper script:
+
+    script/myapp_create.pl view TT TT
+
+where the first C<TT> tells the script that the name of the view should
+be C<TT>, and the second that it should be a Template Toolkit view.)
+
+This gives us a process() method and we can now just do
+$c->forward('MyApp::View::TT') to render our templates. The base class
+makes process() implicit, so we don't have to say
+C<$c-E<gt>forward(qw/MyApp::View::TT process/)>.
+
+    sub hello : Global {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'hello.tt';
+    }
+
+    sub end : Private {
+        my ( $self, $c ) = @_;
+        $c->forward( $c->view('TT') );
+    }
+
+You normally render templates at the end of a request, so it's a perfect
+use for the global C<end> action.
+
+In practice, however, you would use a default C<end> action as supplied
+by L<Catalyst::Action::RenderView>.
+
+Also, be sure to put the template under the directory specified in
+C<$c-E<gt>config-E<gt>{root}>, or you'll end up looking at the debug
+screen.
+
+=head4 Models
+
+Models are providers of data. This data could come from anywhere - a
+search engine index, a spreadsheet, the file system - but typically a
+Model represents a database table. The data source does not
+intrinsically have much to do with web applications or Catalyst - it
+could just as easily be used to write an offline report generator or a
+command-line tool.
+
+To show how to define models, again we'll use an already-existing base
+class, this time for L<DBIx::Class>: L<Catalyst::Model::DBIC::Schema>.
+We'll also need L<DBIx::Class::Schema::Loader>.
+
+But first, we need a database.
+
+    -- myapp.sql
+    CREATE TABLE foo (
+        id INTEGER PRIMARY KEY,
+        data TEXT
+    );
+
+    CREATE TABLE bar (
+        id INTEGER PRIMARY KEY,
+        foo INTEGER REFERENCES foo,
+        data TEXT
+    );
+
+    INSERT INTO foo (data) VALUES ('TEST!');
+
+    % sqlite /tmp/myapp.db < myapp.sql
+
+Now we can create a DBIC::Schema model for this database.
+
+    script/myapp_create.pl model MyModel DBIC::Schema MySchema create=static 'dbi:SQLite:/tmp/myapp.db'
+
+L<DBIx::Class::Schema::Loader> automatically loads table layouts and
+relationships, and converts them into a static schema definition C<MySchema>,
+which you can edit later.
+
+Use the stash to pass data to your templates.
+
+We add the following to MyApp/Controller/Root.pm
+
+    sub view : Global {
+        my ( $self, $c, $id ) = @_;
+        
+        $c->stash->{item} = $c->model('MyModel::Foo')->find($id);
+    }
+
+    1;
+    
+    sub end : Private {
+        my ( $self, $c ) = @_;
+        
+        $c->stash->{template} ||= 'index.tt';
+        $c->forward( $c->view('TT') );
+    }
+
+We then create a new template file "root/index.tt" containing:
+
+    The Id's data is [% item.data %]
+
+Models do not have to be part of your Catalyst application; you
+can always call an outside module that serves as your Model:
+
+    # in a Controller
+    sub list : Local {
+      my ( $self, $c ) = @_;
+      
+      $c->stash->{template} = 'list.tt';
+      
+      use Some::Outside::Database::Module;
+      my @records = Some::Outside::Database::Module->search({
+        artist => 'Led Zeppelin',
+        });
+      
+      $c->stash->{records} = \@records;
+    }
+
+But by using a Model that is part of your Catalyst application, you
+gain several things: you don't have to C<use> each component, Catalyst
+will find and load it automatically at compile-time; you can
+C<forward> to the module, which can only be done to Catalyst
+components.  Only Catalyst components can be fetched with
+C<$c-E<gt>model('SomeModel')>.
+
+Happily, since many people have existing Model classes that they
+would like to use with Catalyst (or, conversely, they want to
+write Catalyst models that can be used outside of Catalyst, e.g.
+in a cron job), it's trivial to write a simple component in
+Catalyst that slurps in an outside Model:
+
+    package MyApp::Model::DB;
+    use base qw/Catalyst::Model::DBIC::Schema/;
+    __PACKAGE__->config(
+        schema_class => 'Some::DBIC::Schema',
+        connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}]
+    );
+    1;
+
+and that's it! Now C<Some::DBIC::Schema> is part of your
+Cat app as C<MyApp::Model::DB>.
+
+Within Catalyst, the common approach to writing a model for your
+application is wrapping a generic model (e.g. L<DBIx::Class::Schema>, a
+bunch of XMLs, or anything really) with an object that contains
+configuration data, convenience methods, and so forth. Thus you
+will in effect have two models - a wrapper model that knows something
+about Catalyst and your web application, and a generic model that is
+totally independent of these needs.
+
+Technically, within Catalyst a model is a B<component> - an instance of
+the model's class belonging to the application. It is important to
+stress that the lifetime of these objects is per application, not per
+request.
+
+While the model base class (L<Catalyst::Model>) provides things like
+C<config> to better integrate the model into the application, sometimes
+this is not enough, and the model requires access to C<$c> itself.
+
+Situations where this need might arise include:
+
+=over 4
+
+=item *
+
+Interacting with another model
+
+=item *
+
+Using per-request data to control behavior
+
+=item *
+
+Using plugins from a Model (for example L<Catalyst::Plugin::Cache>).
+
+=back
+
+From a style perspective it's usually considered bad form to make your
+model "too smart" about things - it should worry about business logic
+and leave the integration details to the controllers. If, however, you
+find that it does not make sense at all to use an auxillary controller
+around the model, and the model's need to access C<$c> cannot be
+sidestepped, there exists a power tool called L</ACCEPT_CONTEXT>.
+
+=head4 Controllers
+
+Multiple controllers are a good way to separate logical domains of your
+application.
+
+    package MyApp::Controller::Login;
+
+    use base qw/Catalyst::Controller/;
+
+    sub login : Path("login") { }
+    sub new_password : Path("new-password") { }
+    sub logout : Path("logout") { }
+
+    package MyApp::Controller::Catalog;
+
+    use base qw/Catalyst::Controller/;
+
+    sub view : Local { }
+    sub list : Local { }
+
+    package MyApp::Controller::Cart;
+
+    use base qw/Catalyst::Controller/;
+
+    sub add : Local { }
+    sub update : Local { }
+    sub order : Local { }
+
+Note that you can also supply attributes via the Controller's config so
+long as you have at least one attribute on a subref to be exported
+(:Action is commonly used for this) - for example the following is
+equivalent to the same controller above:
+
+    package MyApp::Controller::Login;
+
+    use base qw/Catalyst::Controller/;
+
+    __PACKAGE__->config(
+      actions => {
+        'sign_in' => { Path => 'sign-in' },
+        'new_password' => { Path => 'new-password' },
+        'sign_out' => { Path => 'sign-out' },
+      },
+    );
+
+    sub sign_in : Action { }
+    sub new_password : Action { }
+    sub sign_out : Action { }
+
+=head3 ACCEPT_CONTEXT
+
+Whenever you call $c->component("Foo") you get back an object - the
+instance of the model. If the component supports the C<ACCEPT_CONTEXT>
+method instead of returning the model itself, the return value of C<<
+$model->ACCEPT_CONTEXT( $c ) >> will be used.
+
+This means that whenever your model/view/controller needs to talk to C<$c> it
+gets a chance to do this when it's needed.
+
+A typical C<ACCEPT_CONTEXT> method will either clone the model and return one
+with the context object set, or it will return a thin wrapper that contains
+C<$c> and delegates to the per-application model object.
+
+A typical C<ACCEPT_CONTEXT> method could look like this:
+
+    sub ACCEPT_CONTEXT {
+      my ( $self, $c, @extra_arguments ) = @_;
+      bless { %$self, c => $c }, ref($self);
+    }
+
+effectively treating $self as a B<prototype object> that gets a new parameter.
+C<@extra_arguments> comes from any trailing arguments to
+C<< $c->component( $bah, @extra_arguments ) >> (or C<< $c->model(...) >>,
+C<< $c->view(...) >> etc).
+
+The life time of this value is B<per usage>, and not per request. To make this
+per request you can use the following technique:
+
+Add a field to C<$c>, like C<my_model_instance>. Then write your
+C<ACCEPT_CONTEXT> method to look like this:
+
+    sub ACCEPT_CONTEXT {
+      my ( $self, $c ) = @_;
+
+      if ( my $per_request = $c->my_model_instance ) {
+        return $per_request;
+      } else {
+        my $new_instance = bless { %$self, c => $c }, ref($self);
+        Scalar::Util::weaken($new_instance->{c}); # or we have a circular reference
+        $c->my_model_instance( $new_instance );
+        return $new_instance;
+      }
+    }
+
 =head3 Application Class
 
 In addition to the Model, View, and Controller components, there's a
 single class that represents your application itself. This is where you
-configure your application, load plugins, define application-wide
-actions, and extend Catalyst.
+configure your application, load plugins, and extend Catalyst.
 
     package MyApp;
 
     use strict;
-    use Catalyst qw/-Debug/;
+    use Catalyst qw/-Debug/; # Add other plugins here, e.g.
+                             # for session support
 
     MyApp->config(
         name => 'My Application',
@@ -198,16 +558,12 @@ actions, and extend Catalyst.
         # You can put anything else you want in here:
         my_configuration_variable => 'something',
     );
-
-    sub default : Private {
-        my ( $self, $context ) = @_;
-        $context->response->body('Catalyst rocks!');
-    }
-
     1;
 
-For most applications, Catalyst requires you to define only one config
-parameter:
+In older versions of Catalyst, the application class was where you put
+global actions. However, as of version 5.66, the recommended practice is
+to place such actions in a special Root controller (see L</Actions>,
+below), to avoid namespace collisions.
 
 =over 4
 
@@ -259,6 +615,7 @@ query parameters, cookies, uploads, headers, and more.
     $c->req->cookies->{sessionid};
     $c->req->headers->content_type;
     $c->req->base;
+    $c->req->uri_with( { page = $pager->next_page } );
 
 =item * L<Catalyst::Response>
 
@@ -288,6 +645,10 @@ information.
 
     $c->stash
     $c->stash->{foo} = 'bar';
+    $c->stash->{baz} = {baz => 'qox'};
+    $c->stash->{fred} = [qw/wilma pebbles/];
+
+and so on.
 
 =back
 
@@ -307,7 +668,9 @@ application components. For an example, we return to our 'hello' action:
 
 Note that the stash should be used only for passing data in an
 individual request cycle; it gets cleared at a new request. If you need
-to maintain more persistent data, use a session.
+to maintain persistent data, use a session. See
+L<Catalyst::Plugin::Session> for a comprehensive set of
+Catalyst-friendly session-handling tools.
 
 =head3 Actions
 
@@ -319,6 +682,29 @@ http://localhost.3000/foo/bar) consists of two parts, the base
 note that the trailing slash after the hostname[:port] always belongs to
 base and not to the action.
 
+=over 4
+
+=item * B<Application Wide Actions>
+
+Actions which are called at the root level of the application
+(e.g. http://localhost:3000/ ) go in MyApp::Controller::Root, like
+this:
+
+    package MyApp::Controller::Root;
+    use base 'Catalyst::Controller';
+    # Sets the actions in this controller to be registered with no prefix
+    # so they function identically to actions created in MyApp.pm
+    __PACKAGE__->config->{namespace} = '';
+    sub default : Private {
+        my ( $self, $context ) = @_;
+        $context->response->body('Catalyst rocks!');
+    }
+    1;
+
+=back
+
+=head4 Action types
+
 Catalyst supports several types of actions:
 
 =over 4
@@ -385,11 +771,15 @@ L</URL Path Handling> below.
 
 =item * B<Top-level> (B<Global>)
 
-    package MyApp; 
+    package MyApp::Controller::Foo;
     sub foo : Global { }
 
-Matches http://localhost:3000/foo. The function name is mapped directly
-to the application base.
+Matches http://localhost:3000/foo. The function name is mapped
+directly to the application base.  You can provide an equivalent
+function in this case  by doing the following:
+
+    package MyApp::Controller::Root
+    sub foo : Local { }
 
 =item * B<Namespace-Prefixed> (B<Local>)
 
@@ -406,6 +796,24 @@ Catalyst ("MyApp::Controller" in the above example), replaces "::" with
 explanation of the pre-defined meaning of Catalyst component class
 names.
 
+=item * B<Chained>
+
+Catalyst also provides a method to build and dispatch chains of actions,
+like
+
+    sub catalog : Chained : CaptureArgs(1) {
+        my ( $self, $c, $arg ) = @_;
+        ...
+    }
+
+    sub item : Chained('catalog') : Args(1) {
+        my ( $self, $c, $arg ) = @_;
+        ...
+    }
+
+to handle a C</catalog/*/item/*> path. For further information about this
+dispatch type, please see L<Catalyst::DispatchType::Chained>.
+
 =item * B<Private>
 
     sub foo : Private { }
@@ -425,9 +833,9 @@ C<$c-E<gt>forward('/catalog/order/process/bar')>.
 
 =item * B<Args>
 
-Args is not an action type per se, but an action modifier - it adds a match
-restriction to any action it's provided to, requiring only as many path parts
-as are specified for the action to be valid - for example in
+Args is not an action type per se, but an action modifier - it adds a
+match restriction to any action it's provided to, requiring only as many
+path parts as are specified for the action to be valid - for example in
 MyApp::Controller::Foo,
 
   sub bar :Local
@@ -459,10 +867,12 @@ displaying a generic frontpage for the main app, or an error page for
 individual controllers.
 
 If C<default> isn't acting how you would expect, look at using a
-L</Literal> C<Path> action (with an empty path string). The difference is
-that C<Path> takes arguments relative from the namespace and C<default>
-I<always> takes arguments relative from the root, regardless of what
-controller it's in.
+L</Literal> C<Path> action (with an empty path string). The difference
+is that C<Path> takes arguments relative from the namespace and
+C<default> I<always> takes arguments relative from the root, regardless
+of what controller it's in. Indeed, this is now the recommended way of
+handling default situations; the C<default> private controller should
+be considered deprecated.
 
 =item * B<index : Private>
 
@@ -498,6 +908,10 @@ run in place of C<MyApp::begin> if you're in the C<catalog> namespace,
 and C<MyApp::Controller::Catalog::Order::begin> would override this in
 turn.
 
+=over 4
+
+=item * B<auto : Private>
+
 In addition to the normal built-in actions, you have a special action
 for making chains, C<auto>. Such C<auto> actions will be run after any
 C<begin>, but before your action is processed. Unlike the other
@@ -506,6 +920,8 @@ called in turn, starting with the application class and going through to
 the I<most> specific class. I<This is the reverse of the order in which
 the normal built-ins override each other>.
 
+=back
+
 Here are some examples of the order in which the various built-ins
 would be called:
 
@@ -553,7 +969,7 @@ authentication fails, returning 0 would skip any remaining methods
 for that URL.
 
 B<Note:> Looking at it another way, C<auto> actions have to return a
-true value to continue processing! You can also C<die> in the autochain
+true value to continue processing! You can also C<die> in the auto
 action; in that case, the request will go straight to the finalize
 stage, without processing further actions.
 
@@ -632,10 +1048,9 @@ debugging enabled).
         $c->res->body( $c->stash->{message} );
     }
 
-A C<forward> does not create a new request, so your request
-object (C<$c-E<gt>req>) will remain unchanged. This is a
-key difference between using C<forward> and issuing a
-redirect.
+A C<forward> does not create a new request, so your request object
+(C<$c-E<gt>req>) will remain unchanged. This is a key difference between
+using C<forward> and issuing a redirect.
 
 You can pass new arguments to a C<forward> by adding them
 in an anonymous array. In this case C<$c-E<gt>req-E<gt>args>
@@ -695,256 +1110,53 @@ the C<detach>ed action and not return to the calling sub. In both cases,
 Catalyst will automatically try to call process() if you omit the
 method.
 
-=head3 Components
-
-Catalyst has an uncommonly flexible component system. You can define as
-many L</Models>, L</Views>, and L</Controllers> as you like.
-
-All components must inherit from L<Catalyst::Base>, which provides a
-simple class structure and some common class methods like C<config> and
-C<new> (constructor).
-
-    package MyApp::Controller::Catalog;
-
-    use strict;
-    use base 'Catalyst::Base';
-
-    __PACKAGE__->config( foo => 'bar' );
-
-    1;
-
-You don't have to C<use> or otherwise register Models, Views, and
-Controllers.  Catalyst automatically discovers and instantiates them
-when you call C<setup> in the main application. All you need to do is
-put them in directories named for each Component type. Notice that you
-can use some very terse aliases for each one.
-
-=over 4
-
-=item * B<MyApp/Model/> 
-
-=item * B<MyApp/M/>
-
-=item * B<MyApp/View/>
-
-=item * B<MyApp/V/>
-
-=item * B<MyApp/Controller/>
-
-=item * B<MyApp/C/>
-
-=back
-
-=head4 Views
-
-To show how to define views, we'll use an already-existing base class for the
-L<Template Toolkit|Template>, L<Catalyst::View::TT>. All we need to do is
-inherit from this class:
-
-    package MyApp::View::TT;
-
-    use strict;
-    use base 'Catalyst::View::TT';
-
-    1;
-
-(You can also generate this automatically by using the helper script:
-
-    script/myapp_create.pl view TT TT
-
-where the first C<TT> tells the script that the name of the view should
-be C<TT>, and the second that it should be a Template Toolkit view.)
-
-This gives us a process() method and we can now just do
-$c->forward('MyApp::View::TT') to render our templates. The base class
-makes process() implicit, so we don't have to say
-C<$c-E<gt>forward(qw/MyApp::View::TT process/)>.
-
-    sub hello : Global {
-        my ( $self, $c ) = @_;
-        $c->stash->{template} = 'hello.tt';
-    }
-
-    sub end : Private {
-        my ( $self, $c ) = @_;
-        $c->forward('MyApp::View::TT');
-    }
-
-You normally render templates at the end of a request, so it's a perfect
-use for the global C<end> action.
-
-Also, be sure to put the template under the directory specified in
-C<$c-E<gt>config-E<gt>{root}>, or you'll be forced to look at our
-eyecandy debug screen. ;)
-
-=head4 Models
-
-To show how to define models, again we'll use an already-existing base
-class, this time for L<DBIx::Class>: L<Catalyst::Model::DBIC::Schema>.
-We'll also need L<DBIx::Class::Schema::Loader>.
-
-But first, we need a database.
-
-    -- myapp.sql
-    CREATE TABLE foo (
-        id INTEGER PRIMARY KEY,
-        data TEXT
-    );
 
-    CREATE TABLE bar (
-        id INTEGER PRIMARY KEY,
-        foo INTEGER REFERENCES foo,
-        data TEXT
-    );
-
-    INSERT INTO foo (data) VALUES ('TEST!');
-
-
-    % sqlite /tmp/myapp.db < myapp.sql
-
-Now we can create a DBIC::SchemaLoader component for this database.
-
-    script/myapp_create.pl model DBIC DBIC::SchemaLoader 'dbi:SQLite:/tmp/myapp.db'
-
-L<DBIx::Class::Schema::Loader> automatically loads table layouts and
-relationships. Use the stash to pass data to your templates.
-
-We add the following to MyApp/Controller/Root.pm
-
-    sub view : Global {
-        my ( $self, $c, $id ) = @_;
-        
-        $c->stash->{item} = $c->model('DBIC::Foo')->find($id);
-    }
-
-    1;
-    
-    sub end : Private {
-        my ( $self, $c ) = @_;
-        
-        $c->stash->{template} ||= 'index.tt';
-        $c->forward( $c->view('TT') );
-    }
-
-We then create a new template file "root/index.tt" containing:
-
-    The Id's data is [% item.data %]
-
-Models do not have to be part of your Catalyst application; you
-can always call an outside module that serves as your Model:
-
-    # in a Controller
-    sub list : Local {
-      my ( $self, $c ) = @_;
-      
-      $c->stash->{template} = 'list.tt';
-      
-      use Some::Outside::DBIC::Module;
-      my @records = Some::Outside::DBIC::Module->search({
-        artist => 'sri',
-        });
-      
-      $c->stash->{records} = \@records;
-    }
-
-But by using a Model that is part of your Catalyst application, you gain
-several things: you don't have to C<use> each component, Catalyst will
-find and load it automatically at compile-time; you can C<forward> to
-the module, which can only be done to Catalyst components; and only
-Catalyst components can be fetched with
-C<$c-E<gt>model('SomeModel')>.
-
-Happily, since many people have existing Model classes that they
-would like to use with Catalyst (or, conversely, they want to
-write Catalyst models that can be used outside of Catalyst, e.g.
-in a cron job), it's trivial to write a simple component in
-Catalyst that slurps in an outside Model:
-
-    package MyApp::Model::DB;
-    use base qw/Catalyst::Model::DBIC::Schema/;
-    __PACKAGE__->config(
-        schema_class => 'Some::DBIC::Schema',
-        connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}]
-    );
-    1;
-
-and that's it! Now C<Some::DBIC::Schema> is part of your
-Cat app as C<MyApp::Model::DB>.
-
-=head4 Controllers
-
-Multiple controllers are a good way to separate logical domains of your
-application.
-
-    package MyApp::Controller::Login;
-
-    use base qw/Catalyst::Controller/;
-
-    sub sign_in : Path("sign-in") { }
-    sub new_password : Path("new-password") { }
-    sub sign_out : Path("sign-out") { }
-
-    package MyApp::Controller::Catalog;
-
-    use base qw/Catalyst::Controller/;
-
-    sub view : Local { }
-    sub list : Local { }
-
-    package MyApp::Controller::Cart;
+=head3 Testing
 
-    use base qw/Catalyst::Controller/;
+Catalyst has a built-in http server for testing or local
+deployment. (Later, you can easily use a more powerful server, for
+example Apache/mod_perl or FastCGI, in a production environment.)
 
-    sub add : Local { }
-    sub update : Local { }
-    sub order : Local { }
+Start your application on the command line...
 
-Note that you can also supply attributes via the Controller's config so long
-as you have at least one attribute on a subref to be exported (:Action is
-commonly used for this) - for example the following is equivalent to the same
-controller above
+    script/myapp_server.pl
 
-    package MyApp::Controller::Login;
+...then visit http://localhost:3000/ in a browser to view the output.
 
-    use base qw/Catalyst::Controller/;
+You can also do it all from the command line:
 
-    __PACKAGE__->config(
-      actions => {
-        'sign_in' => { Path => 'sign-in' },
-        'new_password' => { Path => 'new-password' },
-        'sign_out' => { Path => 'sign-out' },
-      },
-    );
+    script/myapp_test.pl http://localhost/
 
-    sub sign_in : Action { }
-    sub new_password : Action { }
-    sub sign_out : Action { }
+Catalyst has a number of tools for actual regression testing of
+applications. The helper scripts will automatically generate basic tests
+that can be extended as you develop your project. To write your own
+comprehensive test scripts, L<Test::WWW::Mechanize::Catalyst> is an
+invaluable tool.
 
-=head3 Testing
+For more testing ideas, see L<Catalyst::Manual::Tutorial::Testing>.
 
-Catalyst has a built-in http server for testing! (Later, you can easily
-use a more powerful server, e.g. Apache/mod_perl, in a production
-environment.)
+Have fun!
 
-Start your application on the command line...
+=head1 SEE ALSO
 
-    script/myapp_server.pl
+=over 4
 
-...then visit http://localhost:3000/ in a browser to view the output.
+=item * L<Catalyst::Manual::About>
 
-You can also do it all from the command line:
+=item * L<Catalyst::Manual::Tutorial>
 
-    script/myapp_test.pl http://localhost/
+=item * L<Catalyst>
 
-Have fun!
+=back
 
 =head1 SUPPORT
 
 IRC:
 
     Join #catalyst on irc.perl.org.
+    Join #catalyst-dev on irc.perl.org to help with development.
 
-Mailing-lists:
+Mailing lists:
 
     http://lists.rawmode.org/mailman/listinfo/catalyst
     http://lists.rawmode.org/mailman/listinfo/catalyst-dev
@@ -956,8 +1168,10 @@ David Naughton, C<naughton@umn.edu>
 Marcus Ramberg, C<mramberg@cpan.org>
 Jesse Sheidlower, C<jester@panix.com>
 Danijel Milicevic, C<me@danijel.de>
+Kieren Diment, C<kd@totaldatasolution.com>
+Yuval Kogman, C<nothingmuch@woobling.org>
 
 =head1 COPYRIGHT
 
-This program is free software, you can redistribute it and/or modify it
+This program is free software. You can redistribute it and/or modify it
 under the same terms as Perl itself.