template render hook?

17 views
Skip to first unread message

Brian

unread,
Oct 17, 2016, 10:51:21 PM10/17/16
to Perl Kelp
Do you have a suggestion for the best way to duplicate something like the Dancer 'before template render' hook?  This is executed before a template is rendered and gives the code a way to add parameters to the list being passed into the template.  I would use it, for example, to look up whether the user is logged in and/or whether the user is an admin.  This will let me set is_admin and is_logged_in and stuff like user_id into every template hash instead of making me add it to each and every call to template().  I'm using Template::Toolkit, btw.

Thanks,
Brian

Brian

unread,
Oct 17, 2016, 11:00:35 PM10/17/16
to Perl Kelp
Just for the record, I tried overriding the template() method, adding to the params, and then calling the parent template() method and returning, but I got an error.  Example:

sub template {
    my ($self, $template, $params) = @_;

    $params->{'is_logged_in'} ||= $self->is_logged_in();

    return $self->SUPER::template($template, $params);
}

Error:

brian@metal:/home/fan$ plackup -L Shotgun app.psgi
HTTP::Server::PSGI: Accepting connections at http://0:5000/
Error while loading /home/fan/app.psgi: Redefining of Fan::Web::template not allowed at /home/brian/perl5/lib/perl5/Kelp.pm line 105.

Stefan Geneshky

unread,
Oct 18, 2016, 6:24:00 PM10/18/16
to perl...@googlegroups.com
The template method (part of the Kelp::Response class) already passes a reference to your application instance via the app variable. So, if you have an application method called is_logged_in, you can access it in the templates via app.is_logged_in.

If you absolutely have to have a shortcut to is_logged_in, then the best approach is to create your own Response class, which overrides the template function.

package Fan::Response;
use Kelp::Base 'Kelp::Response';

sub template {
    my ( $self, $template, $vars, @rest ) = @_;
    $vars->{is_logged_in} = $self->app->is_logged_in;  # is_logged_in is now available in the templates
    return $self->SUPER::template($template, $vars, @rest);
}

You will have to tell Kelp to use your "custom" response class instead of the default one:

my $app = Fan->new( response_obj => 'Fan::Response' );

Alternatively, you can override the build_response method in Fan.pm as shown here:
https://metacpan.org/pod/Kelp#build_request (this example shows how to override a request, but overriding the response is just as easy)

I hope that helps.

Stefan

Brian E. Lozier

unread,
Oct 18, 2016, 9:21:07 PM10/18/16
to perl...@googlegroups.com
Thanks for the reply.  I ended up creating a new method, "tpl" which does the same thing as my example template() override method I posted above.  It just adds to the parameter list and then calls the parent template() method.

Your suggestions also make sense; I'll keep them in mind if I need to expand further in this direction.

I'm actually curious about the error message though:


Error while loading /home/fan/app.psgi: Redefining of Fan::Web::template not allowed at /home/brian/perl5/lib/perl5/Kelp.pm line 105.

If Fan::Web inherits from Kelp, and Kelp is providing the template() method, why won't simply overriding it work?  I initially thought there was some magic going on in the parent that was explicitly disallowing overrides but reading it further it says redefining Fan::Web::template is not allowed, which sort of indicates that my child class method was defined first.  Any idea what I'm missing?  And if you're intentionally prohibiting overriding of certain methods, what is the reasoning behind that?

Stefan Geneshky

unread,
Oct 18, 2016, 10:25:34 PM10/18/16
to perl...@googlegroups.com
There is no magic. It's hard to tell what's going on without context. Create a Github gist with your code (you can remove your business logic) and I'll tell you what's causing this error.

Brtastic

unread,
Apr 15, 2020, 12:05:29 PM4/15/20
to Perl Kelp
Just for the future reference, have a look at my module: https://metacpan.org/pod/KelpX::Hooks
It enables you to do exactly what you need here
Reply all
Reply to author
Forward
0 new messages