Shitload of ::Manual fixes, add some FIXMEs which I'll get to shortly
[catagits/Catalyst-Manual.git] / lib / Catalyst / Manual / Cookbook.pod
index 6a4c2fc..d6da3c8 100644 (file)
@@ -112,14 +112,22 @@ reference.
 
 =head3 EXAMPLE
 
-  use parent qw/Catalyst/;
+  package MyApp;
+  use Moose;
+  use namespace::autoclean;
+
   use Catalyst  qw/
                          Session
                          Session::Store::FastMmap
                          Session::State::Cookie
                    /;
+  extends 'Catalyst';
+  __PACKAGE__->setup;
 
-
+  package MyApp::Controller::Foo;
+  use Moose;
+  use namespace::autoclean;
+  BEGIN { extends 'Catalyst::Controller';
   ## Write data into the session
 
   sub add_item : Local {
@@ -254,47 +262,7 @@ like so:
       }
     }
 
-
-=head2 Role-based Authorization
-
-For more advanced access control, you may want to consider using role-based
-authorization. This means you can assign different roles to each user, e.g.
-"user", "admin", etc.
-
-The C<login> and C<logout> methods and view template are exactly the same as
-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/;
-
-Roles are implemented automatically when using
-L<Catalyst::Authentication::Store::Htpasswd>:
-
-  # no additional role configuration required
-  __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile";
-
-Or can be set up manually when using L<Catalyst::Authentication::Store::DBIC>:
-
-  # Authorization using a many-to-many role relationship
-  __PACKAGE__->config->{authorization}{dbic} = {
-    'role_class'           => 'My::Model::DBIC::Role',
-    'role_field'           => 'name',
-    'user_role_user_field' => 'user',
-
-    # DBIx::Class only (omit if using Class::DBI)
-    'role_rel'             => 'user_role',
-
-    # Class::DBI only, (omit if using DBIx::Class)
-    'user_role_class'      => 'My::Model::CDBI::UserRole'
-    'user_role_role_field' => 'role',
-  };
+=head2 FIXME
 
 To restrict access to any action, you can use the C<check_user_roles> method:
 
@@ -314,7 +282,7 @@ error if the current user does not have one of the required roles:
     my ( $self, $c ) = @_;
     $c->assert_user_roles( qw/ user admin / );
   }
-  
+
 =head2 Authentication/Authorization
 
 This is done in several steps:
@@ -388,7 +356,7 @@ then be assigned to ACLs, or just checked when needed.
 =head3 Logging in
 
 When you have chosen your modules, all you need to do is call the C<<
-$c->login >> method. If called with no parameters, it will try to find
+$c->authenticate >> method. If called with no parameters, it will try to find
 suitable parameters, such as B<username> and B<password>, or you can
 pass it these values.
 
@@ -401,21 +369,34 @@ the user is a member.
 
 =head3 EXAMPLE
 
- use parent qw/Catalyst/;
+ package MyApp;
+ use Moose;
+ use namespace::autoclean;
+ extends qw/Catalyst/;
  use Catalyst qw/Authentication
-                 Authentication::Credential::Password
-                 Authentication::Store::Htpasswd
                  Authorization::Roles/;
 
- __PACKAGE__->config->{authentication}{htpasswd} = "passwdfile";
-
-  sub login : Local {
+ __PACKAGE__->config(
+    'Plugin::Authentication' => {
+        default => {
+            credential => {
+                class => 'Htpasswd',
+                # FIXME
+            },
+            store => {
+                class => 'Null',
+            },
+        },
+    },
+ );
+
+ sub login : Local {
      my ($self, $c) = @_;
 
      if (    my $user = $c->req->param("user")
          and my $password = $c->req->param("password") )
      {
-         if ( $c->login( $user, $password ) ) {
+         if ( $c->authenticate( username => $user, password => $password ) ) {
               $c->res->body( "hello " . $c->user->name );
          } else {
             # login incorrect
@@ -451,6 +432,7 @@ use the testing instead of production database.
 
 e.g.,
 
+  # FIXME - Out of date
   use Catalyst::Plugin::Authentication::Store::Minimal::Backend;
 
   # Sets up the user `test_user' with password `test_pass'
@@ -500,7 +482,7 @@ control checks. Let's load it:
 
     use parent qw/Catalyst/;
     use Catalyst qw/
-                    Authentication # yadda yadda
+                    Authentication
                     Authorization::Roles
                   /;
 
@@ -646,7 +628,7 @@ inherits from DBIx::Class::Schema
     sub connection {
         my ($self, @rest) = @_;
         $self->next::method(@rest);
-        # $self is now a live My::Schema object, complete with DB connection 
+        # $self is now a live My::Schema object, complete with DB connection
 
         $self->ACCESSORNAME1([ $self->resultset('RESULTSOURCEMONIKER')->all ]);
         $self->ACCESSORNAME2([ $self->resultset('RESULTSOURCEMONIKER')->search({ COLUMN => { '<' => '30' } })->all ]);
@@ -762,8 +744,6 @@ enforce a specific one.
         my ( $self, $c, $a, $b ) = @_;
         return RPC::XML::int->new( $a + $b );
     }
-    
-
 
 =head1 Views
 
@@ -841,7 +821,7 @@ This time, the helper sets several options for us in the generated View.
 
 =over
 
-=item 
+=item
 
 INCLUDE_PATH defines the directories that Template Toolkit should search
 for the template files.
@@ -988,7 +968,7 @@ L<http://search.cpan.org/perldoc?Catalyst%3A%3AView%3A%3ATT>
 
 L<http://search.cpan.org/perldoc?Template>
 
-=head2 Adding RSS feeds 
+=head2 Adding RSS feeds
 
 Adding RSS feeds to your Catalyst applications is simple. We'll see two
 different aproaches here, but the basic premise is that you forward to
@@ -1005,7 +985,7 @@ This is the aproach used in Agave (L<http://dev.rawmode.org/>).
         $c->stash->{template}='rss.tt';
     }
 
-Then you need a template. Here's the one from Agave: 
+Then you need a template. Here's the one from Agave:
 
     <?xml version="1.0" encoding="UTF-8"?>
     <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
@@ -1018,7 +998,7 @@ Then you need a template. Here's the one from Agave:
      [% WHILE (post = posts.next) %]
       <item>
         <title>[% post.title %]</title>
-        <description>[% post.formatted_teaser|html%]</description>    
+        <description>[% post.formatted_teaser|html%]</description>
         <pubDate>[% post.pub_date %]</pubDate>
         <guid>[% post.full_uri %]</guid>
         <link>[% post.full_uri %]</link>
@@ -1026,7 +1006,7 @@ Then you need a template. Here's the one from Agave:
       </item>
     [% END %]
       </channel>
-    </rss> 
+    </rss>
 
 =head3 Using XML::Feed
 
@@ -1056,7 +1036,7 @@ like this:
    }
 
 A little more code in the controller, but with this approach you're
-pretty sure to get something that validates. 
+pretty sure to get something that validates.
 
 Note that for both of the above aproaches, you'll need to set the
 content type like this:
@@ -1141,12 +1121,12 @@ you can set it up like this:
 
     sub render : ActionClass('RenderView') { }
 
-    sub end : Private { 
+    sub end : Private {
       my ( $self, $c ) = @_;
       $c->forward('render');
       # do stuff here
     }
-  
+
 =head2 Action Types
 
 =head3 Introduction
@@ -1191,7 +1171,7 @@ and
 
  sub my_handles : Path('/handles') { .. }
 
-becomes 
+becomes
 
  http://localhost:3000/handles
 
@@ -1232,7 +1212,7 @@ matches
 
  http://localhost:3000/handles
 
-and 
+and
 
  http://localhost:3000/handles_and_other_parts
 
@@ -1290,7 +1270,7 @@ the request object using C<< $c->req->path >>.
 works for all unknown URLs, in this controller namespace, or every one
 if put directly into MyApp.pm.
 
-=item index 
+=item index
 
 The index action is called when someone tries to visit the exact
 namespace of your controller. If index, default and matching Path
@@ -1313,7 +1293,7 @@ to the current namespace.
 
  sub begin : Private { .. }
 
-is called once when 
+is called once when
 
  http://localhost:3000/bucket/(anything)?
 
@@ -1342,14 +1322,14 @@ chain of paths up to and including the ending namespace, will be
 called. (In contrast, only one of the begin/end/default actions will
 be called, the relevant one).
 
- package MyApp.pm;
+ package MyApp::Controller::Root;
  sub auto : Private { .. }
 
-and 
+and
 
  sub auto : Private { .. }
 
-will both be called when visiting 
+will both be called when visiting
 
  http://localhost:3000/bucket/(anything)?
 
@@ -1359,14 +1339,11 @@ will both be called when visiting
 
 =head3 A word of warning
 
-Due to possible namespace conflicts with Plugins, it is advised to
-only put the pre-defined Private actions in your main MyApp.pm file,
-all others should go in a Controller module.
+You can put root actions in your main MyApp.pm file, but this is deprecated,
+please put your actions into your Root controller.
 
 =head3 More Information
 
-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.
@@ -1378,7 +1355,7 @@ Imagine that you would like the following paths in your application:
 =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>>
@@ -1391,41 +1368,41 @@ 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 
+
+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.
 
@@ -1537,7 +1514,7 @@ the Catalyst Request object:
   $c->req->args([qw/arg1 arg2 arg3/]);
   $c->forward('/wherever');
 
-(See the L<Catalyst::Manual::Intro> Flow_Control section for more 
+(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.
@@ -1545,7 +1522,7 @@ information on passing arguments via C<forward>.)
   package MyApp::Controller::Base;
   use base qw/Catalyst::Controller/;
 
-  sub key1 : Chained('/') 
+  sub key1 : Chained('/')
 
 =head1 Deployment
 
@@ -1600,7 +1577,7 @@ to run a Catalyst app.
 
 =head4 1. Install Catalyst::Engine::Apache
 
-You should install the latest versions of both Catalyst and 
+You should install the latest versions of both Catalyst and
 Catalyst::Engine::Apache.  The Apache engines were separated from the
 Catalyst core in version 5.50 to allow for updates to the engine without
 requiring a new Catalyst release.
@@ -1627,7 +1604,7 @@ Here is a basic Apache 2 configuration.
 
     PerlSwitches -I/var/www/MyApp/lib
     PerlModule MyApp
-    
+
     <Location />
         SetHandler          modperl
         PerlResponseHandler MyApp
@@ -1659,7 +1636,7 @@ of your choice.
         SetHandler          modperl
         PerlResponseHandler MyApp
     </Location>
-    
+
 When running this way, it is best to make use of the C<uri_for> method in
 Catalyst for constructing correct links.
 
@@ -1671,7 +1648,7 @@ Static files can be served directly by Apache for a performance boost.
     <Location /static>
         SetHandler default-handler
     </Location>
-    
+
 This will let all files within root/static be handled directly by Apache.  In
 a two-tiered setup, the frontend server should handle static files.
 The configuration to do this on the frontend will vary.
@@ -1801,10 +1778,10 @@ for example, libapache2-mod-fastcgi in Debian.
 
     FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -processes 3
     Alias /myapp/ /var/www/MyApp/script/myapp_fastcgi.pl/
-    
+
     # Or, run at the root
     Alias / /var/www/MyApp/script/myapp_fastcgi.pl/
-    
+
 The above commands will launch 3 app processes and make the app available at
 /myapp/
 
@@ -1816,12 +1793,12 @@ server gives you much more flexibility.
 First, launch your app as a standalone server listening on a socket.
 
     script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5 -p /tmp/myapp.pid -d
-    
+
 You can also listen on a TCP port if your web server is not on the same
 machine.
 
     script/myapp_fastcgi.pl -l :8080 -n 5 -p /tmp/myapp.pid -d
-    
+
 You will probably want to write an init script to handle starting/stopping
 of the app using the pid file.
 
@@ -1835,10 +1812,10 @@ Now, we simply configure Apache to connect to the running server.
 
     FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket
     Alias /myapp/ /tmp/myapp.fcgi/
-    
+
     # Or, run at the root
     Alias / /tmp/myapp.fcgi/
-    
+
 =head3 More Info
 
 L<Catalyst::Engine::FastCGI>.
@@ -1902,7 +1879,7 @@ Make sure mod_proxy is enabled and add:
     ProxyPass / http://localhost:8080/
     ProxyPassReverse / http://localhost:8080/
 
-    # This is optional if you'd like to show a custom error page 
+    # 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
 
@@ -1940,11 +1917,11 @@ L<Module::Install::Catalyst>, which simplifies the process greatly.  From the sh
     % perl Makefile.PL
     % make catalyst_par
 
-You can customise the PAR creation process by special "catalyst_par_*" commands 
-available from L<Module::Install::Catalyst>. You can add these commands in your 
+You can customise the PAR creation process by special "catalyst_par_*" commands
+available from L<Module::Install::Catalyst>. You can add these commands in your
 Makefile.PL just before the line containing "catalyst;"
 
-    #Makefile.PL example with extra PAR options 
+    #Makefile.PL example with extra PAR options
     use inc::Module::Install;
 
     name 'MyApp';
@@ -2057,7 +2034,7 @@ Static::Simple look somewhere else, this is as easy as:
 
  MyApp->config->{static}->{include_path} = [
   MyApp->config->{root},
-  '/path/to/my/files' 
+  '/path/to/my/files'
  ];
 
 When you override include_path, it will not automatically append the
@@ -2082,7 +2059,7 @@ be processed by Catalyst): B<tmpl, tt, tt2, html, xhtml>. This list can
 be replaced easily:
 
  MyApp->config->{static}->{ignore_extensions} = [
-    qw/tmpl tt tt2 html xhtml/ 
+    qw/tmpl tt tt2 html xhtml/
  ];
 
 =item Ignoring directories
@@ -2113,7 +2090,7 @@ static content to the view, perhaps like this:
     sub end : Private {
         my ( $self, $c ) = @_;
 
-        $c->forward( 'MyApp::View::TT' ) 
+        $c->forward( 'MyApp::View::TT' )
           unless ( $c->res->body || !$c->stash->{template} );
     }
 
@@ -2221,18 +2198,18 @@ application for a cache because the source document changes
 infrequently but may be viewed many times.
 
     use Catalyst qw/Cache::FileCache/;
-    
+
     ...
-    
+
     use File::stat;
     sub render_pod : Local {
         my ( self, $c ) = @_;
-        
+
         # the cache is keyed on the filename and the modification time
         # to check for updates to the file.
         my $file  = $c->path_to( 'root', '2005', '11.pod' );
         my $mtime = ( stat $file )->mtime;
-        
+
         my $cached_pod = $c->cache->get("$file $mtime");
         if ( !$cached_pod ) {
             $cached_pod = do_slow_pod_rendering();
@@ -2241,7 +2218,7 @@ infrequently but may be viewed many times.
         }
         $c->stash->{pod} = $cached_pod;
     }
-    
+
 We could actually cache the result forever, but using a value such as 12 hours
 allows old entries to be automatically expired when they are no longer needed.
 
@@ -2258,26 +2235,26 @@ thing for every single user who views the page.
 
     sub front_page : Path('/') {
         my ( $self, $c ) = @_;
-        
+
         $c->forward( 'get_news_articles' );
         $c->forward( 'build_lots_of_boxes' );
         $c->forward( 'more_slow_stuff' );
-        
+
         $c->stash->{template} = 'index.tt';
     }
 
 We can add the PageCache plugin to speed things up.
 
     use Catalyst qw/Cache::FileCache PageCache/;
-    
+
     sub front_page : Path ('/') {
         my ( $self, $c ) = @_;
-        
+
         $c->cache_page( 300 );
-        
+
         # same processing as above
     }
-    
+
 Now the entire output of the front page, from <html> to </html>, will be
 cached for 5 minutes.  After 5 minutes, the next request will rebuild the
 page and it will be re-cached.
@@ -2290,14 +2267,14 @@ You can even get that front-end Squid proxy to help out by enabling HTTP
 headers for the cached page.
 
     MyApp->config->{page_cache}->{set_http_headers} = 1;
-    
+
 This would now set the following headers so proxies and browsers may cache
 the content themselves.
 
     Cache-Control: max-age=($expire_time - time)
     Expires: $expire_time
     Last-Modified: $cache_created_time
-    
+
 =head3 Template Caching
 
 Template Toolkit provides support for caching compiled versions of your
@@ -2306,17 +2283,17 @@ TT will cache compiled templates keyed on the file mtime, so changes will
 still be automatically detected.
 
     package MyApp::View::TT;
-    
+
     use strict;
     use warnings;
     use base 'Catalyst::View::TT';
-    
+
     __PACKAGE__->config(
         COMPILE_DIR => '/tmp/template_cache',
     );
-    
+
     1;
-    
+
 =head3 More Info
 
 See the documentation for each cache plugin for more details and other
@@ -2337,10 +2314,10 @@ alterations.
 
 =head2 Testing
 
-Catalyst provides a convenient way of testing your application during 
+Catalyst provides a convenient way of testing your application during
 development and before deployment in a real environment.
 
-C<Catalyst::Test> makes it possible to run the same tests both locally 
+C<Catalyst::Test> makes it possible to run the same tests both locally
 (without an external daemon) and against a remote server via HTTP.
 
 =head3 Tests
@@ -2362,7 +2339,7 @@ response.
 
 =item C<02pod.t>
 
-Verifies that all POD is free from errors. Only executed if the C<TEST_POD> 
+Verifies that all POD is free from errors. Only executed if the C<TEST_POD>
 environment variable is true.
 
 =item C<03podcoverage.t>
@@ -2404,18 +2381,18 @@ take three different arguments:
 
 =back
 
-C<request> returns an instance of C<HTTP::Response> and C<get> returns the 
+C<request> returns an instance of C<HTTP::Response> and C<get> returns the
 content (body) of the response.
 
 =head3 Running tests locally
 
     mundus:~/MyApp chansen$ CATALYST_DEBUG=0 TEST_POD=1 prove --lib lib/ t/
-    t/01app............ok                                                        
-    t/02pod............ok                                                        
-    t/03podcoverage....ok                                                        
+    t/01app............ok
+    t/02pod............ok
+    t/03podcoverage....ok
     All tests successful.
     Files=3, Tests=4,  2 wallclock secs ( 1.60 cusr +  0.36 csys =  1.96 CPU)
+
 C<CATALYST_DEBUG=0> ensures that debugging is off; if it's enabled you
 will see debug logs between tests.
 
@@ -2427,12 +2404,12 @@ find out more about it from the links below.
 =head3 Running tests remotely
 
     mundus:~/MyApp chansen$ CATALYST_SERVER=http://localhost:3000/ prove --lib lib/ t/01app.t
-    t/01app....ok                                                                
+    t/01app....ok
     All tests successful.
     Files=1, Tests=2,  0 wallclock secs ( 0.40 cusr +  0.01 csys =  0.41 CPU)
 
-C<CATALYST_SERVER=http://localhost:3000/> is the absolute deployment URI of 
-your application. In C<CGI> or C<FastCGI> it should be the host and path 
+C<CATALYST_SERVER=http://localhost:3000/> is the absolute deployment URI of
+your application. In C<CGI> or C<FastCGI> it should be the host and path
 to the script.
 
 =head3 C<Test::WWW::Mechanize> and Catalyst
@@ -2531,13 +2508,13 @@ Sebastian Riedel C<sri@oook.de>
 
 Danijel Milicevic C<me@danijel.de>
 
-Viljo Marrandi C<vilts@yahoo.com>  
+Viljo Marrandi C<vilts@yahoo.com>
 
 Marcus Ramberg C<mramberg@cpan.org>
 
 Jesse Sheidlower C<jester@panix.com>
 
-Andy Grundman C<andy@hybridized.org> 
+Andy Grundman C<andy@hybridized.org>
 
 Chisel Wright C<pause@herlpacker.co.uk>