Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a template_path option to Mojolicious::Renderer::render #1782

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/Mojolicious/Controller.pm
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,8 @@ automatically discarded.
Non-persistent data storage and exchange for the current request, application wide default values can be set with
L<Mojolicious/"defaults">. Some stash values have a special meaning and are reserved, the full list is currently
C<action>, C<app>, C<cb>, C<controller>, C<data>, C<extends>, C<format>, C<handler>, C<inline>, C<json>, C<layout>,
C<namespace>, C<path>, C<status>, C<template>, C<text> and C<variant>. Note that all stash values with a C<mojo.*>
prefix are reserved for internal use.
C<namespace>, C<path>, C<status>, C<template>, C<template_path>, C<text> and C<variant>. Note that all stash values
with a C<mojo.*> prefix are reserved for internal use.

# Remove value
my $foo = delete $c->stash->{foo};
Expand Down
5 changes: 5 additions & 0 deletions lib/Mojolicious/Guides/Rendering.pod
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ L<Mojolicious::Controller/"render_maybe"> to try multiple alternatives.

$c->render_maybe('localized/baz') or $c->render('foo/bar/baz');

If you want to render a template from a specific file not in a C<templates> directory, you can pass it with the
C<template_path> option.

$c->render(template_path => '/path/to/the/template');

=head2 Rendering to strings

Sometimes you might want to use the rendered result directly instead of generating a response, for example, to send
Expand Down
21 changes: 13 additions & 8 deletions lib/Mojolicious/Renderer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ sub render {

my $stash = $c->stash;
my $options = {
encoding => $self->encoding,
handler => $stash->{handler},
template => delete $stash->{template},
variant => $stash->{variant}
encoding => $self->encoding,
handler => $stash->{handler},
template => delete $stash->{template},
template_path => delete $stash->{template_path},
variant => $stash->{variant}
};
my $inline = $options->{inline} = delete $stash->{inline};
$options->{handler} //= $self->default_handler if defined $inline;
Expand All @@ -102,12 +103,13 @@ sub render {
return encode_json(delete $stash->{json}), 'json' if exists $stash->{json};

# Template or templateless handler
$options->{template} //= $self->template_for($c);
return () unless $self->_render_template($c, \my $output, $options);
$options->{template} //= $self->template_for($c) unless $options->{template_path};
return () unless $self->_render_template($c, \my $output, $options);

# Inheritance
my $content = $stash->{'mojo.content'} //= {};
local $content->{content} = $output =~ /\S/ ? $output : undef if $stash->{extends} || $stash->{layout};
delete $options->{template_path};
while ((my $next = _next($stash)) && !defined $inline) {
@$options{qw(handler template)} = ($stash->{handler}, $next);
$options->{format} = $stash->{format} || $self->default_format;
Expand Down Expand Up @@ -162,6 +164,7 @@ sub template_handler {
sub template_name {
my ($self, $options) = @_;

return $options->{template_path} if $options->{template_path};
return undef unless defined(my $template = $options->{template});
return undef unless my $format = $options->{format};
$template .= ".$format";
Expand All @@ -181,6 +184,7 @@ sub template_name {

sub template_path {
my ($self, $options) = @_;
return $options->{template_path} if $options->{template_path};
return undef unless my $name = $self->template_name($options);
my @parts = split /\//, $name;
-r and return $_ for map { path($_, @parts)->to_string } @{$self->paths}, $TEMPLATES;
Expand Down Expand Up @@ -434,7 +438,7 @@ handler could be found.
});

Return a template name for an options hash reference with C<template>, C<format>, C<variant> and C<handler> values, or
C<undef> if no template could be found, usually used by handlers.
C<undef> if no template could be found, usually used by handlers. If C<template_path> is passed then return it as-is.

=head2 template_path

Expand All @@ -445,7 +449,8 @@ C<undef> if no template could be found, usually used by handlers.
});

Return the full template path for an options hash reference with C<template>, C<format>, C<variant> and C<handler>
values, or C<undef> if the file does not exist in L</"paths">, usually used by handlers.
values, or C<undef> if the file does not exist in L</"paths">, usually used by handlers. If C<template_path> is
passed then return it as-is.

=head2 warmup

Expand Down
6 changes: 6 additions & 0 deletions t/mojolicious/layouted_lite_app.t
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ get '/variants' => [format => ['txt']] => {layout => 'variants', format => undef
$c->render('variants');
};

get '/specific_template' => {template_path => curfile->sibling('templates2')->child('42.html.ep')->to_string};

my $t = Test::Mojo->new;

subtest '"0" content reassignment' => sub {
Expand Down Expand Up @@ -282,6 +284,10 @@ subtest 'Variants ("0")' => sub {
->content_is('Another variant: Desktop!');
};

subtest 'Specific template path' => sub {
$t->get_ok('/specific_template')->status_is(200)->content_is("DefaultThe answer is 42.\n\n");
};

done_testing();

__DATA__
Expand Down