Navigation Menu

Skip to content

Commit

Permalink
allow routes to be rearranged at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Jul 20, 2014
1 parent 906b141 commit 4b9fc41
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 9 deletions.
4 changes: 3 additions & 1 deletion Changes
@@ -1,5 +1,7 @@

5.16 2014-07-19
5.16 2014-07-20
- Added empty method to Mojo::Cache.
- Added flush method to Mojolicious::Routes.

5.15 2014-07-17
- Improved Mojo::DOM::HTML performance slightly.
Expand Down
10 changes: 9 additions & 1 deletion lib/Mojo/Cache.pm
Expand Up @@ -3,14 +3,16 @@ use Mojo::Base -base;

has 'max_keys' => 100;

sub empty { delete shift->{cache} }

sub get { (shift->{cache} || {})->{shift()} }

sub set {
my ($self, $key, $value) = @_;

my $cache = $self->{cache} ||= {};
my $queue = $self->{queue} ||= [];
delete $cache->{shift @$queue} if @$queue >= $self->max_keys;
delete $cache->{shift @$queue} while @$queue >= $self->max_keys;
push @$queue, $key unless exists $cache->{$key};
$cache->{$key} = $value;

Expand Down Expand Up @@ -53,6 +55,12 @@ Maximum number of cache keys, defaults to C<100>.
L<Mojo::Cache> inherits all methods from L<Mojo::Base> and implements the
following new ones.
=head2 empty
$cache->empty;
Empty cache.
=head2 get
my $value = $cache->get('foo');
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/UserAgent/CookieJar.pm
Expand Up @@ -36,7 +36,7 @@ sub all {
return map { @{$jar->{$_}} } sort keys %$jar;
}

sub empty { shift->{jar} = {} }
sub empty { delete shift->{jar} }

sub extract {
my ($self, $tx) = @_;
Expand Down
11 changes: 6 additions & 5 deletions lib/Mojolicious/Guides/Routing.pod
Expand Up @@ -804,10 +804,10 @@ unescaped and decoded from bytes to characters.

=head2 Rearranging routes

Until the first request has been handled, all routes can still be moved around
or even removed with methods like L<Mojolicious::Routes::Route/"add_child">
and L<Mojolicious::Routes::Route/"remove">. Especially for rearranging routes
created by plugins this can be very useful.
All routes can be moved around or even removed with methods like
L<Mojolicious::Routes::Route/"add_child"> and
L<Mojolicious::Routes::Route/"remove">, after the first request has been
handled this can affect performance though.

# GET /example/show -> {controller => 'example', action => 'show'}
my $show = $r->get('/show')->to('example#show');
Expand All @@ -817,7 +817,8 @@ created by plugins this can be very useful.
$r->get('/secrets/show')->to('secrets#show')->name('show_secrets');
$r->find('show_secrets')->remove;

To find routes by their name you can use L<Mojolicious::Routes::Route/"find">.
Especially for rearranging routes created by plugins this can be very useful,
L<Mojolicious::Routes::Route/"find"> is used to locate routes by their name.

=head2 Conditions

Expand Down
12 changes: 12 additions & 0 deletions lib/Mojolicious/Routes.pm
Expand Up @@ -53,6 +53,12 @@ sub dispatch {
return 1;
}

sub flush {
my $self = shift;
if (my $cache = $self->cache) { $cache->empty }
delete $self->{reverse};
}

sub hide { push @{shift->hidden}, @_ }

sub is_hidden {
Expand Down Expand Up @@ -334,6 +340,12 @@ every action.
Match routes with L</"match"> and dispatch with L</"continue">.
=head2 flush
$r->flush;
Flush caches and allow routes to be changed again.
=head2 hide
$r = $r->hide(qw(foo bar));
Expand Down
1 change: 1 addition & 0 deletions lib/Mojolicious/Routes/Route.pm
Expand Up @@ -115,6 +115,7 @@ sub put { shift->_generate_route(PUT => @_) }
sub remove {
my $self = shift;
return $self unless my $parent = $self->parent;
$self->root->flush;
@{$parent->children} = grep { $_ ne $self } @{$parent->children};
return $self->parent(undef);
}
Expand Down
7 changes: 7 additions & 0 deletions t/mojo/cache.t
Expand Up @@ -19,6 +19,13 @@ is $cache->get('foo'), undef, 'no result';
is $cache->get('bar'), undef, 'no result';
is $cache->get('baz'), 'yada', 'right result';
is $cache->get('yada'), 23, 'right result';
$cache->empty;
is $cache->get('baz'), undef, 'no result';
is $cache->get('yada'), undef, 'no result';
$cache->max_keys(1)->set(one => 1)->set(two => 2)->set(three => 3);
is $cache->get('one'), undef, 'no result';
is $cache->get('two'), undef, 'no result';
is $cache->get('three'), 3, 'right result';

$cache = Mojo::Cache->new(max_keys => 3);
is $cache->get('foo'), undef, 'no result';
Expand Down
8 changes: 8 additions & 0 deletions t/mojolicious/app.t
Expand Up @@ -269,6 +269,14 @@ $t->get_ok('/happy/fun/time' => {'X-Test' => 'Hi there!'})->status_is(200)
->header_is('X-Bender' => undef)->header_is(Server => 'Mojolicious (Perl)')
->content_is('Have fun!');

# Foo::index (modify routes at runtime)
ok $t->app->routes->cache, 'routes are cached';
$t->get_ok('/foo/index')->content_like(qr/Hello Mojo/);
$t->app->routes->get('/foo/index' => {text => 'new route'});
$t->app->routes->add_child($t->app->routes->find('default'));
$t->get_ok('/foo/index')->content_is('new route');
ok $t->app->routes->cache, 'routes are still cached';

# Foo::test
$t->get_ok('/foo/test' => {'X-Test' => 'Hi there!'})->status_is(200)
->header_is('X-Bender' => 'Bite my shiny metal ass!')
Expand Down
2 changes: 1 addition & 1 deletion t/mojolicious/lib/MojoliciousTest.pm
Expand Up @@ -156,7 +156,7 @@ sub startup {
$r->route('/rss.xml')->to('foo#bar', format => 'rss');

# /*/* (the default route)
$r->route('/(controller)/(action)')->to(action => 'index');
$r->route('/(controller)/(action)')->to(action => 'index')->name('default');

# /just/some/template (embedded template)
$r->route('/just/some/template')->to(template => 'just/some/template');
Expand Down
2 changes: 2 additions & 0 deletions t/mojolicious/routes.t
Expand Up @@ -181,7 +181,9 @@ my $third = $source->route('/third')->to('#third');
my $target = $r->remove->route('/target')->to('target#');
my $second = $r->find('second');
is $second->render('', {}), '/source/second', 'right result';
is $r->cache(0)->lookup('second'), $second, 'route does exist';
$second->remove;
isnt $r->lookup('second'), $second, 'route does not exist';
is $second->render('', {}), '/second', 'right result';
$target->add_child($first)->add_child($second);
is $second->render('', {}), '/target/second', 'right result';
Expand Down

0 comments on commit 4b9fc41

Please sign in to comment.