Intro: using outside Models in Cat
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Manual / Intro.pod
index d4c19ac..cb09eeb 100644 (file)
@@ -376,10 +376,11 @@ application, by calling the C<forward> method:
     $c->forward('foo');
 
 See L</Flow Control> for a full explanation of C<forward>. Note that, as
-discussed there, when forwarding from another component, you must use the
-absolute path to the method, so that a private C<bar> method in your
-C<MyApp::Controller::Catalog::Order::Process> controller must, if called from
-elsewhere, be reach with C<$c-E<gt>forward('/catalog/order/process/bar')>.
+discussed there, when forwarding from another component, you must use
+the absolute path to the method, so that a private C<bar> method in your
+C<MyApp::Controller::Catalog::Order::Process> controller must, if called
+from elsewhere, be reached with
+C<$c-E<gt>forward('/catalog/order/process/bar')>.
 
 =back
 
@@ -390,66 +391,84 @@ components in your C<forward>s.
 
 =head4 Built-in Private Actions
 
-In response to specific application states, Catalyst will automatically call
-these built-in private actions:
+In response to specific application states, Catalyst will automatically
+call these built-in private actions in your application class:
 
 =over 4
 
 =item * B<default : Private>
 
-Called when no other action matches.
+Called when no other action matches. Could be used, for example, for
+displaying a generic frontpage for the main app, or an error page for
+individual controllers.
 
 =item * B<begin : Private>
 
-Called at the beginning of a request, before any matching actions are called.
+Called at the beginning of a request, before any matching actions are
+called.
 
 =item * B<end : Private>
 
-=back
-
 Called at the end of a request, after all matching actions are called.
 
-=head4 B<Built-in actions in controllers/autochaining>
+=back
+
+=head4 Built-in actions in controllers/autochaining
 
     Package MyApp::C::Foo;
     sub begin : Private { }
     sub default : Private { }
-
-You can define the Built-in Private Actions within your controllers as 
-well. The actions will override the ones in lower level controllers or
-your global application.
-
-In addition to the normal built-ins, you have a special action for 
-making inheritance chains, 'auto'. These will be run after C<begin>, 
-but before your action is processed.
+    sub auto : Private { }
+
+You can define built-in private actions within your controllers as
+well. The actions will override the ones in less-specific controllers,
+or your application class. In other words, for each of the three
+built-in private actions, only one will be run in any request
+cycle. Thus, if C<MyApp::C::Catalog::begin> exists, it will be run in
+place of C<MyApp::begin> if you're in the C<catalog> namespace, and
+C<MyApp::C::Catalog::Order::begin> would override this in turn.
+
+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
+built-ins, C<auto> actions I<do not> override each other; they will be
+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>.
+
+Here are some examples of the order in which the various built-ins
+would be called:
 
 =over 4
 
-=item for a request for /foo/foo
+=item for a request for C</foo/foo>
 
   MyApp::begin
   MyApp::auto
-  MyApp::C::Foo::default
+  MyApp::C::Foo::default # in the absence of MyApp::C::Foo::Foo
   MyApp::end
 
-=item for a request for /foo/bar/foo
+=item for a request for C</foo/bar/foo>
 
   MyApp::C::Foo::Bar::begin
   MyApp::auto
   MyApp::C::Foo::auto
-  MyApp::C::Foo::Bar::default
+  MyApp::C::Foo::Bar::auto
+  MyApp::C::Foo::Bar::default # for MyApp::C::Foo::Bar::foo
   MyApp::C::Foo::Bar::end
 
 =back
 
-Also, if you need to break out of the chain in one of your auto 
-actions, you can return 0, if so, your action will not be processed,
-but the end will, so for the request above, if the first auto returns
-false, it would look like this:
+The C<auto> action is also distinguished by the fact that you can break
+out of the processing chain by returning 0. If an C<auto> action returns
+0, any remaining actions will be skipped, except for C<end>. So, for the
+request above, if the first auto returns false, the chain would look
+like this:
 
 =over 4
 
-=item for a request for /foo/bar/foo where auto returns false
+=item for a request for C</foo/bar/foo> where first C<auto> returns
+false
 
   MyApp::C::Foo::Bar::begin
   MyApp::auto
@@ -457,22 +476,28 @@ false, it would look like this:
 
 =back
 
-B<Note:> auto actions have to return a true value to continue
-processing!  You can also die in the autochain action, in that case, the
-request will go straight to the finalize stage, without processing
-further actions.
+An example of why one might use this is an authentication action: you
+could set up a C<auto> action to handle authentication in your
+application class (which will always be called first), and if
+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
+action; in that case, the request will go straight to the finalize
+stage, without processing further actions.
 
-=head4 B<URL Argument Handling>
+=head4 URL Path Handling
 
-If you want to pass variable arguments at the end of a URL, you must use regex
-actions keys with '^' and '$' anchors, and the arguments must be separated with
-forward slashes (/) in the URL. For example, suppose you want to handle
-/foo/$bar/$baz, where $bar and $baz may vary:
+You can pass variable arguments as part of the URL path. In this case,
+you must use regex action keys with '^' and '$' anchors, and the
+arguments must be separated with forward slashes (/) in the URL. For
+example, suppose you want to handle C</foo/$bar/$baz>, where C<$bar> and
+C<$baz> may vary:
 
     sub foo : Regex('^foo$') { my ($self, $context, $bar, $baz) = @_; }
 
-But what if you also defined actions for /foo/boo and /foo/boo/hoo ?
+But what if you also defined actions for C</foo/boo> and C</foo/boo/hoo>?
 
     sub boo : Path('foo/boo') { .. }
     sub hoo : Path('foo/boo/hoo') { .. }
@@ -481,15 +506,17 @@ Catalyst matches actions in most specific to least specific order:
 
     /foo/boo/hoo
     /foo/boo
-    /foo # might be /foo/bar/baz
+    /foo # might be /foo/bar/baz but won't be /foo/boo/hoo
 
-So Catalyst would never mistakenly dispatch the first two URLs to the '^foo$' action.
+So Catalyst would never mistakenly dispatch the first two URLs to the
+'^foo$' action.
 
-=head4 B<Parameter Processing>
+=head4 Parameter Processing
 
-Parameters are handled with methods in the L<Catalyst::Request>
-class. The C<param> method is functionally equivalent to the C<param>
-method of C<CGI.pm> and can be used in modules that require this.
+Parameters passed in the URL query string are handled with methods in
+the L<Catalyst::Request> class. The C<param> method is functionally
+equivalent to the C<param> method of C<CGI.pm> and can be used in
+modules that require this.
 
     # http://localhost:3000/catalog/view/?category=hardware&page=3
     my $category = $c->req->param('category');
@@ -503,15 +530,22 @@ method of C<CGI.pm> and can be used in modules that require this.
 
 =head3 Flow Control
 
-You control the application flow with the C<forward> method, which accepts the
-key of an action to execute. A forward is like a method call, only it wraps the 
-call in an eval to allow exception handling, and to pass along the context object,
-and allow profiling of each method.
+You control the application flow with the C<forward> method, which
+accepts the key of an action to execute. This can be an action in the
+same or another Catalyst controller, or a Class name, optionally
+followed by a method name. After a C<forward>, the control flow will
+return to the method from which the C<forward> was issued.
+
+A C<forward> is similar to a method call. The main differences are that
+it wraps the call in an C<eval> to allow exception handling; it
+automatically passes along the context object (C<$c> or C<$context>);
+and it allows profiling of each call (displayed in the log with
+debugging enabled).
 
     sub hello : Global {
         my ( $self, $c ) = @_;
         $c->stash->{message} = 'Hello World!';
-        $c->forward('check_message');
+        $c->forward('check_message'); # $c is automatically included
     }
 
     sub check_message : Private {
@@ -525,28 +559,39 @@ and allow profiling of each method.
         $c->res->output( $c->stash->{message} );
     }
 
-As opposed to a redirect, your request object will remain unchanged, as no actual
-new request is started, unless you pass along new args like this:
+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>
+will be changed for the duration of the C<forward> only; upon
+return, the original value of C<$c-E<gt>req-E<gt>args> will
+be reset.
 
     sub hello : Global {
         my ( $self, $c ) = @_;
         $c->stash->{message} = 'Hello World!';
-        $c->forward('check_message',[qw/test1/);
+        $c->forward('check_message',[qw/test1/]);
+        # now $c->req->args is back to what it was before
     }
 
-In that case, $c->request->argumentss will be changed until you return from the 
-forward.  test1 will also be passed as an argument to check_message after $c.
+    sub check_message : Private {
+        my ( $self, $c ) = @_;
+        my $first_argument = $c->req->args[0]; # now = 'test1'
+        # do something...
+    }
     
-As you can see from these examples, you can just use the method name as long as
-you are referring to methods in the same controller. If you want to forward to a
-method in another controller, or the main application, you will have to refer to
-the method by absolute path.
+As you can see from these examples, you can just use the method name as
+long as you are referring to methods in the same controller. If you want
+to forward to a method in another controller, or the main application,
+you will have to refer to the method by absolute path.
 
   $c->forward('/my/controller/action');
-  $c->forward('/default');
+  $c->forward('/default'); # calls default in main application
 
-You can also forward to classes and methods.
+Here are some examples of how to forward to classes and methods.
 
     sub hello : Global {
         my ( $self, $c ) = @_;
@@ -555,7 +600,7 @@ You can also forward to classes and methods.
 
     sub bye : Global {
         my ( $self, $c ) = @_;
-        $c->forward('MyApp::M::Hello');
+        $c->forward('MyApp::M::Hello'); # no method: will try 'process'
     }
 
     package MyApp::M::Hello;
@@ -570,9 +615,12 @@ You can also forward to classes and methods.
         $c->res->output('Goodbye World!');
     }
 
-Note that C<forward> returns to the calling action and continues processing
-after the action finishes.  Catalyst will automatically try to call process() if
-you omit the method.
+Note that C<forward> returns to the calling action and continues
+processing after the action finishes. If you want all further processing
+in the calling action to stop, use C<detach> instead, which will execute
+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
 
@@ -592,11 +640,11 @@ class structure and some common class methods like C<config> and C<new>
 
     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.
+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
 
@@ -649,12 +697,12 @@ process/)>.
         $c->forward('MyApp::V::TT');
     }
 
-You normally render templates at the end of a request, so it's a perfect use for
-the global C<end> action.
+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. ;)
+C<$c-E<gt>config-E<gt>{root}>, or you'll be forced to look at our
+eyecandy debug screen. ;)
 
 =head4 Models
 
@@ -722,8 +770,41 @@ pass data to your templates.
 
     1;
 
+    # Then, in a TT template:
     The id 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::CDBI::Module;
+      my @records = Some::Outside::CDBI::Module->retrieve_all;
+      $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 componenents; and only
+Catalyst components can be fetched with
+C<$c-E<gt>comp('MyApp::M::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::M::Catalog;
+    use base qw/Catalyst::Base Some::Other::CDBI::Module::Catalog/;
+    1;
+
+and that's it! Now C<Some::Other::CDBI::Module::Catalog> is part of your
+Cat app as C<MyApp::M::Catalog>.
+
 =head4 Controllers
 
 Multiple controllers are a good way to separate logical domains of your