0

from an ajax form this router foundname gets called, I need to process the value and pass it to another router, I can't figured it out how to do it, here is a sample of how I am trying:

#!/usr/bin/perl

use Mojolicious::Lite;

get '/foundname' => sub {

  my $c = shift;
  # Here I get the value from the form
  my $name_on = $c->req->query_params->param('name');

  if($name_on) {
    # call another router and pass the name value to it
    # It gives an error "Can't locate object method "get" ", I might not need to use "get", just don't know how to pass the value.
    $c->get('/process_name')->to( searched => $name_on);
   }

};

 get '/process_name' => sub {

   my $c = shift;
   my $got_name = $c->req->query_params->param('searched');
   ...
 };

Thank you!

Maresia
  • 67
  • 2
  • 2
  • 6
  • Do you want to dynamically install a new route? Your code looks like this. I think that's unlikely and you probably want to just do an internal forward, essentially calling `/process_name`. Is that correct? – simbabque Feb 23 '17 at 16:09
  • Yes, I have several internal routes that needs to communicate like that. – Maresia Feb 23 '17 at 16:20

2 Answers2

1

You need to look up the routes through your Mojolicious::Routes object inside of your app. The name for the lookup is auto-generated by Mojolicious::Lite from the path-part of the URI, so /process_name has the name process_name.

You get back a Mojolicious::Routes::Route, which has a render method and you can pass your parameters along there.

use Mojolicious::Lite;

get '/foundname' => sub {
    my $c = shift;

    my $name_on = $c->req->query_params->param('name');

    if( $name_on ) {
        my $process_name = app->routes->lookup('process_name')->render( { searched => $name_on } );
        $c->render( text => $process_name );
    }
};

get '/process_name' => sub {
   my $c = shift;
   my $got_name = $c->req->query_params->param('searched');

   $c->render( text => $got_name );
};

app->start;

When you curl this you get the parameter back as a response.

$ curl localhost:3000/foundname?name=foo
/process_name

However, this is probably not the right approach. If you want to implement business logic, you should not use internal or hidden routes for that. Remember that your application is still just Perl. You can write a sub and call that.

use Mojolicious::Lite;

get '/foundname' => sub {
    my $c = shift;

    my $name_on = $c->req->query_params->param('name');

    if( $name_on ) {
        my $got_name = process_name( $name_on );
        $c->render( text => $got_name );
    }
};

sub process_name {
    my ( $got_name ) = @_;

    # do stuff with $got_name

    return uc $got_name;
};

app->start;

This will output

$ curl localhost:3000/foundname?name=foo
FOO

It's the more portable approach, as you can easily unit-test these functions. If you want to have $c, you have to pass it along. You also have the app keyword available in any sub you define.

simbabque
  • 53,749
  • 8
  • 73
  • 136
  • I like the second approach since I am converting an app from "standard perl" to a framework style. But that is rising a question to me, when should a sub routine in perl needs to be converted into a router using Mojolicious::Lite? – Maresia Feb 23 '17 at 16:48
  • @Maresia I would only convert the direct access points to _routes_ (not _router_, that's the thing that handles incoming requests). So every entry point has a sub. Mojo calls those _controllers_ (that's why there is a `$c`). Typically you keep those flat. I would go so far as to create separate packages for the business logic and call the functions from there. Or make them objects. – simbabque Feb 23 '17 at 18:06
  • Sorry about the "router" typo. What you said makes sense. Entry point a route, from the route a call to a sub to process data and so on. The documentation is every where, to wide, would you recommend some site with more explanation on this topic? – Maresia Feb 23 '17 at 18:32
  • @Maresia I don't really use Mojolicious. I work with Catalyst and Dancer2. But the strategy is the same everywhere. Read up on [the mvc pattern](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller#Use_in_web_applications), especially how it's used for web applications. If you keep your business logic out of the actual web layer you can easily write tests for it, and it's more portable. – simbabque Feb 23 '17 at 18:39
  • Need to get some more training on this thing, but thanks for the info. – Maresia Feb 23 '17 at 18:58
  • Can I ask you one more question related to converting "standard perl" . In a dispatch table that calls 2 subs how would you approach converting the code into routes? my %data = ( more_data => sub { address( addr => $q->param('addr'), ), acc( zip => $q->param('zip'), ) }, ); my $process = $data{'more_data'}; $process->(); – Maresia Feb 23 '17 at 19:54
  • @Maresia there is no standard Perl. All of this is Perl, it's just different frameworks. You have a CGI script now, and you want to turn it into an MVC-ish application. Think about what the application did before, and how closely you want to map that to your new application. Every entry point is one route. Everything else is business logic. If you don't have the business logic encapsulated yet, maybe doing that first in the old code is a good start. Then you can transfer it step by step. But that's getting very broad and does not fit this question. – simbabque Feb 23 '17 at 21:37
0

For the original question, I would use

$c->redirect_to()

See this question for details on passing the variable over: Passing arguments to redirect_to in mojolicious and using them in the target controller

======

But, I would look more into writing subs (as others have said). If you have existing logic then you can wrap it in a helper or just toss the logic in a helper and call that.

helper('process_name'=> sub{
    my $self,$args = @_;

    # Do some logic with $args->{'name'}
    return $something;
});

get '/foundname' => sub {
    my $c = shift;

    my $name_on = $c->req->query_params->param('name');

    if( $name_on ) {
        my $process_name = $c->process_name({name => $name_on});
        $c->render( text => $process_name );
    }else{
      $c->redner(text => 'Error',status=>500);
    }
};
Community
  • 1
  • 1
shaneburgess
  • 15,702
  • 15
  • 47
  • 66