Search code examples
perlmojolicious

Mojolicious receive post result


I came from perl Cgi's, and i am starting with mojolicious ( and web frameworks too ), using as example this github: https://github.com/webdevesgi/mojolicious-demo

I have this template:

  % layout 'menu2';
   <hr/>


   % if ( stash 'result' ) { 
      <li><%= stash 'result' %></li>
   % } else  { 
      <li>bar</li>
   % } 
  <ul>
  % foreach my $url (keys %$urls) {
      <li><%= $urls->{$url}->{'url_origin'} %> - <a target="blank" href="http://localhost:3000/l/<%= $urls->{$url}->{'url_short'} %>">!<%= $urls->{$url}->{'url_short'} %></a> (<%= $urls->{$url}->{'clics'} %> clics)</li>
  % }
</ul>
<br/>

<%= form_for sendurl => (method => 'post', class => 'well form-search' target = "_self") => begin %>
    <p>Raccourcir une url :
    <%= text_field 'orig_url', class => 'input-xlarge' %>
    <%= submit_button 'GO', class => 'btn btn-warning' %>
    </p>



<% end %>

And i want to view in this template after doing a post, the result of the action, with this lines:

% if ( stash 'result' ) { 
          <li><%= stash 'result' %></li>
       % } else  { 
          <li>bar</li>
       % } 

This is the code for sendurl:

sub sendurl{
  my $self = shift;

  my $url =  Mojo::URL->new($self->param('orig_url'));
  if(!$url->is_abs){
      return $self->redirect_to('dashboard');
  }

  my $short_url = encodeurl($self->param('orig_url'));

  $self->urls->addUrl($self->session('user'), $self->param('orig_url'), $short_url);


  my $params = $self->req->params->to_hash;

  if ($params) {
      $self->stash( 'result' , "Errors - not sent" );
      open F, q[>],'log.txt';print F Dumper $self;close F;
  }

  $self->redirect_to('dashboard', result=> "Errors - not sent");

}

In the log.txt i can see the stash having the value:

 'stash' => {
                          'mojo.session' => {
                                              'user_type' => 'admin',
                                              'user' => 'foo'
                                            },
                          'mojo.captures' => {
                                               'controller' => 'login',
                                               'action' => 'sendurl'
                                             },
                          'menu' => $VAR1->{'app'}{'defaults'}{'config'}{'app_menu'}{'admin'},
                          'urls' => {
                                      '' => {
                                              'url_short' => '!532f1b4f',
                                              'id' => undef,
                                              'url_origin' => 'www.foo.bar/baz',
                                              'clics' => undef
                                            }
                                    },
                          'mojo.active_session' => 2,
                          'mojo.started' => [
                                              1395596194,
                                              529165
                                            ],
                          'controller' => 'login',
                          'mojo.routed' => 1,
                          'action' => 'sendurl',
                          'mojo.secret' => 'login',
                          'config' => $VAR1->{'app'}{'defaults'}{'config'},
                          'result' => 'Errors - not sent'
                        },

But in the web explorer i cant see the value of result

How can i achieve this? How can i pass a a result from sendurl to the view, and in the view check for a result variable in stash is defined? This is the best way to work with mojolicious?


Solution

  • Got time to look more into the problems now. As you have found out, stash entries do not survive a redirect_to, but you can use flash instead.

    I've done some minor changes to the code as well to at least get rid of some of the most peculiar things. After those changes, the debug output from morbo looks sane.

    lib/Login.pm

    Instead of calling a controller action for checking if a user is logged in, use a simple callback:

    my $logged_in = $r->under->to(cb => sub {
      my $self = shift;
      return defined $self->session('user');
    });
    

    lib/Login/Login.pm

    Renamed the logged_in sub to dashboard (which fix the action not found error), and add a proper render call at the end (to render the login/dashboard template).

    sub dashboard {
      my $self = shift;
      $self->stash(
          urls => $self->urls->getUrls($self->session('user')),
      );
      return $self->render;
    }
    

    In sub send_url I changed the $self->stash(result => to flash:

    my $params = $self->req->params->to_hash;
    if ($params) {
      $self->flash(result => "Errors - not sent");
    }
    

    templates/login/dashboard.html.ep

    Your check for result became:

    <li><%= flash('result') // 'result not in flash' %></li>
    

    And some final advices:

    • The database access can be improved a lot. Use the excellent Mojolicious::Plugin::Database instead of trying to figure out how to get things working with prefork/hypnotoad.
    • Never, never, never untar the Mojolicious source code directly into your app! (or checking in the VCS...)
    • Use a proper build environment (EU::MM, M::B etc).
    • Read the Mojolicious documentation, and begin coding in small scale (Mojolicious::Lite) and grow it to a full app if neccessary (following the guidelines in Mojolicious::Guides::Growing).

    Good luck!