Skip to content

Instantly share code, notes, and snippets.

@leejo
Created February 2, 2016 08:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leejo/656dca61264d3480de81 to your computer and use it in GitHub Desktop.
Save leejo/656dca61264d3480de81 to your computer and use it in GitHub Desktop.
Route ordering with default stash values
This is the minimal test case i could reduce to showing the "issue"
it seems the route ordering doesn't matter in all cases until we start
adding default stash values in the `->to` block. i don't know if this
is known behaviour, but it caught us out recently and something to be
aware of:
```perl
#!/usr/bin/env perl
package ExampleApp;
use Mojo::Base qw( Mojolicious );
sub startup {
my ( $self ) = @_;
my $r = $self->routes;
$r->route('/a/b/:foo/:bar/')->to(
controller => 'ExampleController',
action => 'long_urn',
# comment out the below line and the tests will pass
foo => 'a',
);
$r->route('/a/b/c/')->to(
controller => 'ExampleController',
action => 'short_urn'
);
}
package ExampleApp::ExampleController;
use Mojo::Base 'Mojolicious::Controller';
sub long_urn { shift->render( text => 'FIRST' ) }
sub short_urn { shift->render( text => 'SECOND' ) }
package main;
use strict;
use warnings;
use Mojolicious::Commands;
use Test::Mojo;
use Test::Most;
my $t = Test::Mojo->new( 'ExampleApp' );
$t->get_ok( '/a/b/a/b/' )->status_is( 200 )->content_is( "FIRST" );
$t->get_ok( '/a/b/c/' )->status_is( 200 )->content_is( "SECOND" );
$t->get_ok( '/d/e/f/' )->status_is( 404 );
done_testing();
```
@leejo
Copy link
Author

leejo commented Feb 2, 2016

Of course the fix here is $r->route('/a/b/c/') should be defined before $r->route('/a/b/:foo/:bar/') but this perhaps suggests some unexpected behaviour?

@leejo
Copy link
Author

leejo commented Feb 2, 2016

Actually i can reduce this even more:

#!/usr/bin/env perl

package ExampleApp;

use Mojo::Base qw( Mojolicious );

sub startup {
    my ( $self ) = @_;

    my $r = $self->routes;

    $r->route('/a/b/:foo/:bar/')->to(
        controller => 'ExampleController',
        action     => 'long_urn',
        # comment out the below line and the tests will pass
        foo        => 'a',
    );

}

package ExampleApp::ExampleController;

use Mojo::Base 'Mojolicious::Controller';

sub long_urn  { shift->render( text => 'FIRST' ) }
sub short_urn { shift->render( text => 'SECOND' ) }

package main;

use strict;
use warnings;

use Mojolicious::Commands;
use Test::Mojo;
use Test::Most;

my $t = Test::Mojo->new( 'ExampleApp' );

$t->get_ok( '/a/b/a/b/' )->status_is( 200 )->content_is( "FIRST" );
$t->get_ok( '/a/b/c/' )->status_is( 404 );

done_testing();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment