X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FIntro.pod;h=44a80b45605dbfd6ff775355b9d7b6bb226cb343;hp=32e2ba18e04088e87789341c325c2075c80b2393;hb=05a90578a1a58925942d520bf21333c59c6eac01;hpb=8a6a6581d48a3c1c4d5f631cdb7cbda336c0e5e2 diff --git a/lib/Catalyst/Manual/Intro.pod b/lib/Catalyst/Manual/Intro.pod index 32e2ba1..44a80b4 100644 --- a/lib/Catalyst/Manual/Intro.pod +++ b/lib/Catalyst/Manual/Intro.pod @@ -417,249 +417,6 @@ C<$c-Ereq-Ecaptures-E[0]> would be "23". If you want to pass arguments at the end of your URL, you must use regex action keys. See L below. -=item * B - -The C attribute allows you to chain public path parts together -by their private names. A chain part's path can be specified with C -and can be declared to expect an arbitrary number of arguments. The endpoint -of the chain specifies how many arguments it gets through the C -attribute. C<:Args(0)> would be none at all, C<:Args> without an integer -would be unlimited. The path parts that aren't endpoints are using -C to specify how many parameters they expect to receive. As an -example setup: - - package MyApp::Controller::Greeting; - use base qw/ Catalyst::Controller /; - - # this is the beginning of our chain - sub hello : PathPart('hello') Chained('/') CaptureArgs(1) { - my ( $self, $c, $integer ) = @_; - $c->stash->{ message } = "Hello "; - $c->stash->{ arg_sum } = $integer; - } - - # this is our endpoint, because it has no :CaptureArgs - sub world : PathPart('world') Chained('hello') Args(1) { - my ( $self, $c, $integer ) = @_; - $c->stash->{ message } .= "World!"; - $c->stash->{ arg_sum } += $integer; - - $c->response->body( join "
\n" => - $c->stash->{ message }, $c->stash->{ arg_sum } ); - } - -The debug output provides a separate table for chained actions, showing -the whole chain as it would match and the actions it contains. Here's -an example of the startup output with our actions above: - - ... - [debug] Loaded Path Part actions: - .-----------------------+------------------------------. - | Path Spec | Private | - +-----------------------+------------------------------+ - | /hello/*/world/* | /greeting/hello (1) | - | | => /greeting/world | - '-----------------------+------------------------------' - ... - -As you can see, Catalyst only deals with chains as whole path and -builds one for each endpoint, which are the actions with C<:Chained> -but without C<:CaptureArgs>. - -Let's assume this application gets a request at the path -C, what happens then? First, Catalyst will dispatch -to the C action and pass the value C<23> as argument to it after -the context. It does so because we have previously used C<:CaptureArgs(1)> -to declare that it has one path part after itself as it's argument. We -told Catalyst that this is the beginning of the chain by specifying -C<:Chained('/')>. Also note that instead of saying C<:PathPart('hello')> -we could also just have said C<:PathPart>, as it defaults to the name of -the action. - -After C has run, Catalyst goes on to dispatch to the C -action. This is the last action to be called, as Catalyst knows this -is an endpoint because we specified no C<:CaptureArgs> attribute. Nevertheless -we specify that this action expects an argument, but at this point we're -using C<:Args(1)> to do that. We could also have said C<:Args> or leave -it out alltogether, which would mean this action gets all arguments that -are there. This action's C<:Chained> attribute says C and tells -Catalyst that the C action in the current controller is it's -parent. - -With this we have built a chain consisting of two public path parts. -C captures one part of the path as it's argument, and also specifies -the path root as it's parent. So this part is C. The next part -is the endpoint C, expecting one argument. It sums up to the path -part C. This leads to a complete chain of -C which is matched against the requested paths. - -This example application would, if run and called by e.g. -C, set the stash value C to C and -the value C to C<23>. The C action would then append -C to C and add C<12> to the stash's C value. -For the sake of simplicity no view is shown. Instead we just put the -values of the stash into our body. So the output would look like: - - Hello World! - 35 - -And our test server would've given us this debugging output for the -request: - - ... - [debug] "GET" request for "hello/23/world/12" from "127.0.0.1" - [debug] Path is "/greeting/world" - [debug] Arguments are "12" - [info] Request took 0.164113s (6.093/s) - .------------------------------------------+-----------. - | Action | Time | - +------------------------------------------+-----------+ - | /greeting/hello | 0.000029s | - | /greeting/world | 0.000024s | - '------------------------------------------+-----------' - ... - -What would be common usecases of this dispatching technique? It gives the -possibility to split up logic that contains steps that each depend on each -other. An example would be, for example, a wiki path like -C. This chain can be easily built with -these actions: - - sub wiki : PathPart('wiki') Chained('/') CaptureArgs(1) { - my ( $self, $c, $page_name ) = @_; - # load the page named $page_name and put the object - # into the stash - } - - sub rev : PathPart('rev') Chained('wiki') CaptureArgs(1) { - my ( $self, $c, $revision_id ) = @_; - # use the page object in the stash to get at it's - # revision with number $revision_id - } - - sub view : PathPart Chained('rev') Args(0) { - my ( $self, $c ) = @_; - # display the revision in our stash. An other option - # would be to forward a compatible object to the action - # that displays the default wiki pages, unless we want - # a different interface here, for example restore - # functionality. - } - -It would now be possible to add other endpoints. For example C to -restore this specific revision as current state. - -Also, you of course don't have to put all the chained actions in one -controller. The specification of the parent through C<:Chained> also takes -an absolute action path as it's argument. Just specify it with a leading -C. - -If you want, for example, to have actions for the public paths -C and C, just specify two actions with -C<:PathPart('foo')> and C<:Chained('/')>. The handler for the former -path needs a C<:CaptureArgs(1)> attribute and a endpoint with -C<:PathPart('edit')> and C<:Chained('foo')>. For the latter path give -the action just a C<:Args(1)> to mark it as endpoint. This sums up to -this debugging output: - - ... - [debug] Loaded Path Part actions: - .-----------------------+------------------------------. - | Path Spec | Private | - +-----------------------+------------------------------+ - | /foo/* | /controller/foo_view | - | /foo/*/edit | /controller/foo_load (1) | - | | => /controller/edit | - '-----------------------+------------------------------' - ... - -Here's a more detailed specification of the attributes belonging to -C<:Chained>: - -=over 8 - -=item PathPart - -Sets the name of this part of the chain. If it is specified without -arguments, it takes the name of the action as default. So basically -C and C are identical. -This can also contain slashes to bind to a deeper level. An action -with C would bind to -C. If you don't specify C<:PathPart> it has the same -effect as using C<:PathPart>, it would default to the action name. - -=item Chained - -Has to be specified for every child in the chain. Possible values are -absolute and relative private action paths, with the relatives pointing -to the current controller, or a single slash C to tell Catalyst that -this is the root of a chain. The attribute C<:Chained> without aguments -also defaults to the C behaviour. - -Due to the fact that you can specify an absolute path to the parent -action, it doesn't matter to Catalyst where that parent is located. So, -if your design requests it, you can redispatch a chain through every -controller or namespace you want. - -Another interesting possibility gives C<:Chained('.')>, which chains -itself to an action with the path of the current controllers namespace. -For example: - - # in MyApp::Controller::Foo - sub bar : Chained CaptureArgs(1) { ... } - - # in MyApp::Controller::Foo::Bar - sub baz : Chained('.') Args(1) { ... } - -This builds up a chain like C. The specification of C<.> -as argument to Chained here chains the C action to an action with -the path of the current controller namespace, namely C. That -action chains directly to C, so the above chain comes out as end -product. - -=item CaptureArgs - -Also has to be specified for every part of the chain that is not an -endpoint. With this attribute Catalyst knows how many of the following -parts of the path (separated by C) this action wants to captures as -it's arguments. If it doesn't expect any, just specify C<:CaptureArgs(0)>. -The captures get passed to the action's C<@_> right after the context, -but you can also find them as array reference in -C<$c-Erequest-Ecaptures-E[$level]>. The C<$level> is the -level of the action in the chain that captured the parts of the path. - -An action that is part of a chain (read: that has a C<:Chained> attribute) -but has no C<:CaptureArgs> attribute is treated by Catalyst as a chain end. - -=item Args - -By default, endpoints receive the rest of the arguments in the path. You -can tell Catalyst through C<:Args> explicitly how many arguments your -endpoint expects, just like you can with C<:CaptureArgs>. Note that this -also influences if this chain is invoked on a request. A chain with an -endpoint specifying one argument will only match if exactly one argument -exists in the path. - -You can specify an exact number of arguments like C<:Args(3)>, including -C<0>. If you just say C<:Args> without any arguments, it is the same as -leaving it out alltogether: The chain is matched independent of the number -of path parts after the endpoint. - -Just like with C<:CaptureArgs>, the arguments get passed to the action in -C<@_> after the context object. They can also be reached through -C<$c-Erequest-Earguments>. - -=back - -Note that the list of C actions called depends on the private path -of the endpoint of the chain, not on the chained actions way. The C -actions will be run before the chain dispatching begins. In every other -aspect, C actions behave as documented. - -The Cing to other actions does just what you would expect. But if -you C out of a chain, the rest of the chain will not get called -after the C returned. - =item * B (B) package MyApp::Controller::Foo; @@ -687,6 +444,24 @@ Catalyst ("MyApp::Controller" in the above example), replaces "::" with explanation of the pre-defined meaning of Catalyst component class names. +=item * B + +Catalyst also provides a method to build and dispatch chains of actions, +like + + sub foo : Chained : CaptureArgs(1) { + my ( $self, $c, $arg ) = @_; + ... + } + + sub bar : Chained('foo') : Args(1) { + my ( $self, $c, $arg ) = @_; + ... + } + +to handle a C path. For more information about this dispatch +type, please read L. + =item * B sub foo : Private { }