Search code examples
perlmojolicious

Mojo resolving controller and action syntax to subref?


Given a syntax like

$c->routes->get($path)->to("$controller#$sub");

I would like to know which sub $controller#$sub resolves to on dispatch. Is there a simple method to get the ref of the sub? You can hard-set ->namespaces() so I assume it's not always as simple as $controller::$sub because you could have namespace::$controller::$sub.


Solution

  • I could not find a way to do this using the api, but there is a private method _class() that will give the controller object that contains the sub. Here is an example:

    ./lib/MyApp/Controller/Foo.pm:

    package MyApp::Controller::Foo;
    use Mojo::Base 'Mojolicious::Controller';
    sub welcome {
         my $self = shift; 
         $self->render(text => 'Hello there.');
    }    
    1;
    

    ./myapp.pl:

    use strict;
    use warnings;
    use Mojolicious::Lite;
    use lib './lib';
    
    get '/' => sub {
        my $c = shift;
        $c->render(text => 'Hello World!');
    };
    my $namespaces = app->routes->namespaces;
    push @$namespaces, 'MyApp::Controller';
    app->routes->get('/welcome')->to('foo#welcome');
    app->hook(
        before_dispatch => sub {
            my $c = shift;
            my $field = { action => "welcome", controller => "foo" };
            my $obj = $c->app->routes->_class( $c, $field );
            my $method = $field->{action};
            my $subref = sub { $obj->$method( @_ ) };
        }
    );
    app->start;