The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Catalyst::Plugin::ForwardChained - Forwarding to "Chain"-Actions in Catalyst

DESCRIPTION

Forwarding to the end point of a couple of chain methods ..

In most cases: dont use - better user redirect instead

This is a hackaround, not a clean solution.

Experimental.

SYNOPSIS

# In your application class 
use Catalyst qw/ ForwardChained /;

# ... somwhere else:
$c->forward_to_chained( [ qw/ chained endpoint /, [ qw/ args / ] );
$c->forward_to_chained( 'chained/endpoint', [ qw/ args / ] );

Example 1

Having some controller:

package MyApp::Controller::Test;

# ..
# to be clear :
__PACKAGE__->config->{ namespace } = 'test';

# url would be "/one/*"
sub my_index : PathPart( 'one' ) : Chained( '/' ) : CaptureArgs( 1 ) {
    # do some..
}

# url would be "/one/*/two/*"
sub my_other : PathPart( 'two') : Chained( 'my_index' ) : Args( 1 ) {
    # do some..
}

You would use:

# somewhere
#   this would call: "/namespace/one/111/two/222"
$c->forward_to_chained( [ qw/ namespace two / ], [ "111", "222 ] );

# same as above
$c->forward_to_chained( "namespace/two", [ "111", "222 ] );

Example 2

it's not always obvious which path to choose when calling "forward_to_chained" ..

An example testing controller

package MyApp::Controller::Testing;

use strict;
use warnings;

use base qw/ Catalyst::Controller /;
use Data::Dumper;

__PACKAGE__->config->{ namespace } = 'testing';

sub one : PathPart( 'testing/one' ) : Chained( '/' ) : CaptureArgs( 1 ) {
    my ( $self, $c, @args ) = @_;
    push @{ $c->stash->{ called } ||= [] }, {
        name => 'one',
        args => \@args
    };
}

sub two : Chained( 'one' ) : CaptureArgs( 1 ) {
    my ( $self, $c, @args ) = @_;
    push @{ $c->stash->{ called } ||= [] }, {
        name => 'two',
        args => \@args
    };
}

sub three : Chained( 'two' ) {
    my ( $self, $c, @args ) = @_;
    push @{ $c->stash->{ called } ||= [] }, {
        name => 'three',
        args => \@args
    };
}


sub right : PathPart( 'testing/right' ) : Chained( '/' ) : CaptureArgs( 0 ) {
    my ( $self, $c, @args ) = @_;
    push @{ $c->stash->{ called } ||= [] }, {
        name => 'right',
        args => \@args
    };
}

sub again : Chained( 'right' ) : Args( 1 ) {
    my ( $self, $c, @args ) = @_;
    push @{ $c->stash->{ called } ||= [] }, {
        name => 'again',
        args => \@args
    };
}


sub chainor : Local {
    my ( $self, $c ) = @_;
    
    # calling chained:
    
    # 1) WRONG:
    #$c->forward_to_chained( 'testing/one/arg1/two/arg2/three/arg3' );
    
    # 2) WRONG:
    #$c->forward_to_chained( 'testing/one/two/three', [ qw/ arg1 arg2 arg3 arg4 / ] );
    
    # 3) CORRECT:
    $c->forward_to_chained( 'testing/three', [qw/ arg1 arg2 arg3 arg4 /] );
    
    $c->forward_to_chained( 'testing/again', [qw/ arg /] );
    
    $c->res->content_type( 'text/plain' );
    $c->res->body( "Called: \n". Dumper( $c->stash->{ called } ) );
}

1;

would produce something like this:

Called: 
$VAR1 = [
      {
        'args' => [
                    'arg1'
                  ],
        'name' => 'one'
      },
      {
        'args' => [
                    'arg2'
                  ],
        'name' => 'two'
      },
      {
        'args' => [
                    'arg3',
                    'arg4'
                  ],
        'name' => 'three'
      },
      {
        'args' => [],
        'name' => 'right'
      },
      {
        'args' => [
                    'arg'
                  ],
        'name' => 'again'
      }
    ];

and catalyst debug out:

.----------------------------------------------------------------+-----------.
| Action                                                         | Time      |
+----------------------------------------------------------------+-----------+
| /begin                                                         | 0.064814s |
| /testing/chainor                                               | 0.002931s |
| /testing/one                                                   | 0.000588s |
| /testing/two                                                   | 0.000208s |
| /testing/three                                                 | 0.000197s |
| /testing/right                                                 | 0.000061s |
| /testing/again                                                 | 0.000055s |
| /end                                                           | 0.000495s |
'----------------------------------------------------------------+-----------'

METHODS

forward_to_chained

forwards to a certain chained action endpoint ..

$c->forward_to_chained( "some/path", [ qw/ arg1 arg2 arg3 / ] );
$c->forward_to_chained( [qw/ some path /], [ qw/ arg1 arg2 arg3 / ] );

get_chained_action_endpoints

returns array or arrayref of endpoints.. to help you find the one you need

my @endpoints = $c->get_chained_action_endpoints;
my $endpoints_ref = $c->get_chained_action_endpoints;

AUTHOR

Ulrich Kautz, uk@fortrabbit.de