Catalyst cannot go to private actions

On Catalyst, I am trying to dispatch a private action to get some work done. Here is the definition of the function:

sub get_form :Private :Args(1) {
  my ($self, $c, $type_id) = @_;
  #do stuff
}

      

I am trying to route it like this:

$c->forward('get_form',[$type_id]);

      

But it just gives me this error:

Couldn't forward to command "get_form": Invalid action or component.

      

However, if I change the action from :Private

to :Local

, then it works. Does anyone know why this is the case and how to fix it? Thank!

+3


source to share


3 answers


You don't need to, rather, not use :Args(1)

for personal activities in Catalyst.

From the cpan Directory Reference : You can pass new arguments to a direct action by adding them to an anonymous array. In the called (or forwarded) method, you will receive the arguments in $c->req->args

.

sub hello : Global {
    my ( $self, $c ) = @_;
    $c->stash->{message} = 'Hello World!';
    $c->forward('check_message',[qw/test1/]);
}

sub check_message : Private {
    my ( $self, $c, $first_argument ) = @_;
    my $also_first_argument = $c->req->args->[0]; # now = 'test1'
    # do something...
}

      



You can use stash instead $c->stash->{typeid};

. Then you can call the method directly using $c->forward('priv_method');

.

Example:

   sub hello : Global {
        my ( $self, $c ) = @_;
        $c->stash->{message} = 'Hello World!';
        $c->forward('check_message'); # $c is automatically included
    }

    sub check_message : Private {
        my ( $self, $c ) = @_;
        return unless $c->stash->{message};
        $c->forward('show_message');
    }

    sub show_message : Private {
        my ( $self, $c ) = @_;
        $c->res->body( $c->stash->{message} );
    }

      

+7


source


If I was guessing, this is because you say to match certain urls ( :Args(1)

), but :Private

"will never match a url". The Catalyst attribute :Private

is exclusive and does not work with other attributes. "Try passing information through a context object instead.



+3


source


You can also avoid forward () if you like and just call the method if it's the same controller:

sub myaction : Global {
    my ( $self, $c ) = @_;
    $self->dosomething( $c, 'mystring' );
}

sub dosomething {
    my ( $self, $c, $argument ) = @_;
    $c->log->info( $argument );
}

      

While you have to go through $c

, it might be easier to understand.

+3


source







All Articles