simone
simone

Reputation: 5221

Template in Mojolicious controller not found

I am trying to serve a template contained in the __DATA__ section of a controller class, but it doesn't seem to work.

In my main app.pl file I have

#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
use FindBin qw($Bin);
use lib "$Bin/lib";


push @{app->renderer->classes},   'Zairyo::Controller::Data';
push @{app->preload_namespaces},  'Zairyo::Controller::Data';

get '/:uid'  => [uid => qr/[a-z0-9]{32,32}/i ] => { controller => 'Data', action => 'serve_iframe' };

app->start;

and in Zairyo::Controller::Data:

package Zairyo::Controller::Data;

use Mojo::Base 'Mojolicious::Controller', -signatures;

sub serve_iframe ($c) {
    $c->render(template => 'foo');
}

__DATA___

@@ foo.html.ep
what is this

which I'd expect to work as per the documentation but instead throws an error Could not render a response... on the browser and Template "foo.html.ep" not found on the log.

I've solved this by doing

$c->render(inline => data_section(__PACKAGE__, 'foo.html.ep') );

but it seems a bit of a hack.

What am I doing wrong here?

Upvotes: 2

Views: 318

Answers (1)

brian d foy
brian d foy

Reputation: 132758

First, there are a few things a bit off in your Data.pm:

  • There are three underscores after __DATA when there should be two and a newline
  • The module does not return a true value

Here's what I ended up with:

package Zairyo::Controller::Data;

use Mojo::Base 'Mojolicious::Controller', -signatures;

sub serve_iframe ($c) {
    $c->render(template => 'foo' );
}

1;

__DATA__

@@ foo.html.ep
what is this

In the main script, I load the class before I call start. Note that the docs say:

Note that for templates to be detected, these classes need to have already been loaded and added before warmup is called

And, warmup is called immediately by start, and it's warmup that cares about preload_namespaces. You need to get there even sooner, so preload_namespaces does nothing for this particular problem. If you haven't already loaded the module, its __DATA__ templates will not be detected.

#!/usr/bin/env perl
use Mojolicious::Lite -signatures;
use FindBin qw($Bin);
use lib "$Bin/lib";

push @{app->renderer->classes}, map { Mojo::Loader::load_class($_); $_ } 'Zairyo::Controller::Data';

get '/:uid'  => [uid => qr/[a-z0-9]{32,32}/i ] => {
    namespace  => 'Zairyo::Controller',
    controller => 'Data',
    action     => 'serve_iframe'
    };

app->start;

I'm not suggesting this particular code, but now I know why you weren't getting what you wanted.

Upvotes: 3

Related Questions