Search code examples
perlsubroutinemojoliciousmojolicious-lite

How to use my own subroutines (globally) in a Mojolicious::Lite Application


I need to be able to write and call my own subroutines in a Mojolicious::Lite Application. However, the intuitive way to do this doesn't seem to be working. I emailed a colleague who has more Mojolicious experience than I do with this question and he sent me the following code:

#!/usr/bin/env perl
use Mojolicious::Lite;

# Documentation browser under "/perldoc"
plugin 'PODRenderer';

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

sub factorial {
    my $n = shift;
    return $n ? $n * factorial($n - 1) : 1;
}

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!

Five factorial: <%= main::factorial(5) %>

@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
  <head><title><%= title %></title></head>
  <body><%= content %></body>
</html>

But when I run this it tells me that when I'm calling an undefined subroutine:

Undefined subroutine &main::factorial called at template index.html.ep from DATA section line 5, line 32.

I've spent time mucking around with this code, and trying different things that will get it to work, but so far the only thing that makes it run properly is when the subroutine is defined within the scope of the @@ xxx.html.ep's. I've googled/searched stackoverflow for "user defined subroutines in Mojolicious::Lite" and other similar queries. Nothing seems to come up. My searches of the documentation have proved fruitless as well. This seems like it should be a simple task, but I'm a bit stuck. Any help would be appreciated.


Solution

  • As PerC has already mentioned, helpers are the preferred mechanism for adding behaviors (or access to behaviors) to templates. Since he has already shown that example, I will just add that you can make a hybrid of the two by doing something like this (I'm removing the pod renderer plugin, you don't need it).

    #!/usr/bin/env perl
    use Mojolicious::Lite;
    
    get '/' => sub {
      my $self = shift;
      $self->render('index');
    };
    
    sub factorial {
        my $n = shift;
        return $n ? $n * factorial($n - 1) : 1;
    }
    
    helper factorial => sub { shift; factorial(@_) };
    
    app->start;
    __DATA__
    
    @@ index.html.ep
    % layout 'default';
    % title 'Welcome';
    Welcome to the Mojolicious real-time web framework!
    
    Five factorial: <%= factorial(5) %>
    
    @@ layouts/default.html.ep
    <!DOCTYPE html>
    <html>
      <head><title><%= title %></title></head>
      <body><%= content %></body>
    </html>