Expand roles section to contain specific docs on caveats, and version numbers when...
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Cookbook.pod
index 192d3bd..ca49cf3 100644 (file)
@@ -62,7 +62,7 @@ nifty statistics in your debug messages.
 =head2 Enable debug status in the environment
 
 Normally you enable the debugging info by adding the C<-Debug> flag to
-your C<use Catalyst> statement. However, you can also enable it using
+your C<use Catalyst> statement . However, you can also enable it using
 environment variable, so you can (for example) get debug info without
 modifying your application scripts. Just set C<CATALYST_DEBUG> or
 C<E<lt>MYAPPE<gt>_DEBUG> to a true value.
@@ -112,11 +112,12 @@ reference.
 
 =head3 EXAMPLE
 
-  use Catalyst qw/
-                 Session
-                 Session::Store::FastMmap
-                 Session::State::Cookie
-                 /;
+  use parent qw/Catalyst/;
+  use Catalyst  qw/
+                         Session
+                         Session::Store::FastMmap
+                         Session::State::Cookie
+                   /;
 
 
   ## Write data into the session
@@ -266,12 +267,12 @@ in the previous example.
 The L<Catalyst::Plugin::Authorization::Roles> plugin is required when
 implementing roles:
 
+ use parent qw/Catalyst/;
  use Catalyst qw/
-    Authentication
-    Authentication::Credential::Password
-    Authentication::Store::Htpasswd
-    Authorization::Roles
-  /;
+     Authentication
+     Authentication::Credential::Password
+     Authentication::Store::Htpasswd
+     Authorization::Roles/;
 
 Roles are implemented automatically when using
 L<Catalyst::Authentication::Store::Htpasswd>:
@@ -400,6 +401,7 @@ the user is a member.
 
 =head3 EXAMPLE
 
+ use parent qw/Catalyst/;
  use Catalyst qw/Authentication
                  Authentication::Credential::Password
                  Authentication::Store::Htpasswd
@@ -496,10 +498,11 @@ action, so that only a qualified moose feeder can perform that action.
 The Authorization::Roles plugin let's us perform role based access
 control checks. Let's load it:
 
+    use parent qw/Catalyst/;
     use Catalyst qw/
-        Authentication # yadda yadda
-        Authorization::Roles
-    /;
+                    Authentication # yadda yadda
+                    Authorization::Roles
+                  /;
 
 And now our action should look like this:
 
@@ -722,7 +725,7 @@ later) and SOAP::Lite (for XMLRPCsh.pl).
 5. Add a XMLRPC redispatch method and an add method with Remote
 attribute to lib/MyApp/Controller/API.pm
 
-    sub default : Private {
+    sub default :Path {
         my ( $self, $c ) = @_;
         $c->xmlrpc;
     }
@@ -1192,6 +1195,8 @@ becomes
 
  http://localhost:3000/handles
 
+See also: L<Catalyst::DispatchType::Path>
+
 =item Local
 
 When using a Local attribute, no parameters are needed, instead, the
@@ -1233,6 +1238,8 @@ and
 
 etc.
 
+See also: L<Catalyst::DispatchType::Regex>
+
 =item LocalRegex
 
 A LocalRegex is similar to a Regex, except it only matches below the current
@@ -1250,6 +1257,11 @@ and
 
 etc.
 
+=item Chained
+
+See L<Catalyst::DispatchType::Chained> for a description of how the chained
+dispatch type works.
+
 =item Private
 
 Last but not least, there is the Private attribute, which allows you
@@ -1273,7 +1285,7 @@ part of your namespace, you'll get an error page instead. If you want
 to find out where it was the user was trying to go, you can look in
 the request object using C<< $c->req->path >>.
 
- sub default : Private { .. }
+ sub default :Path { .. }
 
 works for all unknown URLs, in this controller namespace, or every one
 if put directly into MyApp.pm.
@@ -1285,7 +1297,7 @@ namespace of your controller. If index, default and matching Path
 actions are defined, then index will be used instead of default and
 Path.
 
- sub index : Private { .. }
+ sub index :Path :Args(0) { .. }
 
 becomes
 
@@ -1357,6 +1369,71 @@ L<http://search.cpan.org/author/SRI/Catalyst-5.61/lib/Catalyst/Manual/Intro.pod>
 
 L<http://dev.catalyst.perl.org/wiki/FlowChart>
 
+=head2 DRY Controllers with Chained actions.
+
+Imagine that you would like the following paths in your application:
+
+=over
+
+=item B</cd/<ID>/track/<ID>>
+
+Displays info on a particular track.
+                                       
+In the case of a multi-volume CD, this is the track sequence.
+
+=item B</cd/<ID>/volume/<ID>/track/<ID>>
+
+Displays info on a track on a specific volume.
+
+=back
+
+Here is some example code, showing how to do this with chained controllers:
+
+    package CD::Controller;
+    use base qw/Catalyst::Controller/;
+    
+    sub root : Chained('/') PathPart('/cd') CaptureArgs(1) {
+        my ($self, $c, $cd_id) = @_;
+        $c->stash->{cd_id} = $cd_id;
+        $c->stash->{cd} = $self->model('CD')->find_by_id($cd_id);
+    }
+    
+    sub trackinfo : Chained('track') PathPart('') Args(0) RenderView {
+        my ($self, $c) = @_;
+    }
+    
+    package CD::Controller::ByTrackSeq;
+    use base qw/CD::Controller/;
+    
+    sub track : Chained('root') PathPart('track') CaptureArgs(1) {
+        my ($self, $c, $track_seq) = @_;
+        $c->stash->{track} = $self->stash->{cd}->find_track_by_seq($track_seq);
+    }
+    
+    package CD::Controller::ByTrackVolNo;
+    use base qw/CD::Controller/;
+    
+    sub volume : Chained('root') PathPart('volume') CaptureArgs(1) {
+        my ($self, $c, $volume) = @_;
+        $c->stash->{volume} = $volume;
+    }
+    
+    sub track : Chained('volume') PathPart('track') CaptureArgs(1) {
+        my ($self, $c, $track_no) = @_;
+        $c->stash->{track} = $self->stash->{cd}->find_track_by_vol_and_track_no(
+            $c->stash->{volume}, $track_no
+        );
+    }
+    
+Note that adding other actions (i.e. chain endpoints) which operate on a track 
+is simply a matter of adding a new sub to CD::Controller - no code is duplicated,
+even though there are two different methods of looking up a track.
+
+This technique can be expanded as needed to fulfil your requirements - for example,
+if you inherit the first action of a chain from a base class, then mixing in a
+different base class can be used to duplicate an entire URL hieratchy at a different
+point within your application.
+
 =head2 Component-based Subrequests
 
 See L<Catalyst::Plugin::SubRequest>.
@@ -1463,6 +1540,12 @@ the Catalyst Request object:
 (See the L<Catalyst::Manual::Intro> Flow_Control section for more 
 information on passing arguments via C<forward>.)
 
+=head2 Chained dispatch using base classes, and inner packages.
+
+  package MyApp::Controller::Base;
+  use base qw/Catalyst::Controller/;
+
+  sub key1 : Chained('/') 
 
 =head1 Deployment
 
@@ -1694,6 +1777,9 @@ can be used without worrying about the thread safety of your application.
 
 =head3 Cons
 
+You may have to disable mod_deflate.  If you experience page hangs with
+mod_fastcgi then remove deflate.load and deflate.conf from mods-enabled/
+
 =head4 More complex environment
 
 With FastCGI, there are more things to monitor and more processes running
@@ -1763,7 +1849,7 @@ The development server is a mini web server written in perl.  If you
 expect a low number of hits or you don't need mod_perl/FastCGI speed,
 you could use the development server as the application server with a
 lightweight proxy web server at the front.  However, consider using
-L<Catalyst::Engine::HTTP::POE> for this kind of deployment instead, since
+L<Catalyst::Engine::HTTP::Prefork> for this kind of deployment instead, since
 it can better handle multiple concurrent requests without forking, or can
 prefork a set number of servers for improved performance.
 
@@ -1808,9 +1894,18 @@ Make sure mod_proxy is enabled and add:
         Order deny,allow
         Allow from all
     </Proxy>
+
+    # Need to specifically stop these paths from being passed to proxy
+    ProxyPass /static !
+    ProxyPass /favicon.ico !
+
     ProxyPass / http://localhost:8080/
     ProxyPassReverse / http://localhost:8080/
 
+    # This is optional if you'd like to show a custom error page 
+    # if the proxy is not available
+    ErrorDocument 502 /static/error_pages/http502.html
+
 You can wrap the above within a VirtualHost container if you want
 different apps served on the same host.
 
@@ -2093,10 +2188,10 @@ There are three wrapper plugins around common CPAN cache modules:
 Cache::FastMmap, Cache::FileCache, and Cache::Memcached.  These can be
 used to cache the result of slow operations.
 
-This very page you're viewing makes use of the FileCache plugin to cache the
+The Catalyst Advent Calendar uses the FileCache plugin to cache the
 rendered XHTML version of the source POD document.  This is an ideal
-application for a cache because the source document changes infrequently but
-may be viewed many times.
+application for a cache because the source document changes
+infrequently but may be viewed many times.
 
     use Catalyst qw/Cache::FileCache/;