5

When I parse html response body I want to find route names for all links found in the body. I use next code snippet:

    my $url =  Mojo::URL->new( $got );
    my $method =  uc( $url->query->clone->param( '_method' ) || 'GET' );
    my $c =  $t->app->build_controller;
    my $m =  Mojolicious::Routes::Match->new( root => $t->app->routes );

    $m->find( $c => { method => $method,  path => $url->path } );

Then $m->endpoint->name gives me the name of route.

But is there more simple way to find route name by given path?

I am looking for something like: $app->routes->find( '/api/v/users/146/link/7QRgs' ) which should return user_hash_check because I have next route:

$guest->get( '/users/:id/link/:hash', 'user_hash_check' )->to( 'user#hash_check' );
Eugen Konkov
  • 22,193
  • 17
  • 108
  • 158
  • Out of curiosity, when do you use this? Are your parsing your own application's website? – simbabque Jan 04 '17 at 15:12
  • 1
    @simbabque: Yes, I do. Actually I use this in tests – Eugen Konkov Jan 04 '17 at 15:15
  • Interesting approach. Is simply clicking the links not sufficient? – simbabque Jan 04 '17 at 15:16
  • What's the problem with the solution you posted? Is it expensive? Or did you just forget you can create a sub? – ikegami Jan 04 '17 at 15:19
  • 1
    @ikegami: I think for this common case the sub should already exists in Mojolicious – Eugen Konkov Jan 04 '17 at 15:23
  • 1
    Doesn't sound very common to me! – ikegami Jan 04 '17 at 15:23
  • 1
    @ikegami: Mojolicious when got request it creates route which is accessible as `$c->match`. So somewhere it already converts `path` string into `route` object. Also there [note about reversibility](http://mojolicious.org/perldoc/Mojolicious/Guides/Routing#Reversibility). To render route into path I can: `$r->lookup( 'route_name' )->render({ foo => 'bar' })`. But I did not find easy way to get route by path, except those five lines of code in question that I should put into sub – Eugen Konkov Jan 04 '17 at 15:30
  • I agree with @ikegami that it's probably enough to just wrap this up in a sub and hide it in the test somewhere. If you want, you can inject it into the namespace of `$t` and make it a method, so you could do your own `$->url_matches_any_route($url)`. It would have to do some basic Test::Builder interaction, but you can easily borrow that from any other testing module, and return `$t`. – simbabque Jan 04 '17 at 15:58

1 Answers1

-1

I have found only one place where we can find route by path. That is Mojolicious::Routes::Match and there is no other way to do this

The one ugly thing here to my mind is requirement to supply Mojolicious::Controller object. But controller is only required to make decision: dispatch or not dispatch Because it has extra info to make this decision: this is data to check conditions

The problem as I think is because of here are mixed two things:

  1. Request
  2. Path

And find should just return all routes matched against given arguments: path and method. Like selectors does The array result maybe cached (now routes with conditions are not cached)

Then dispatcher should check conditions against each route, not matcher. Here each condition may be called in context of right controller and not default one. And this will fix this issue. The routes have in most cases their own controller class have not?

Until this behavior will be fixed the example in the question is the best way to find routes

Eugen Konkov
  • 22,193
  • 17
  • 108
  • 158