Skip to content

Commit

Permalink
improved Mojolicious to use MyApp::Controller namespace by default an…
Browse files Browse the repository at this point in the history
…d encourage its use in the documentation
  • Loading branch information
kraih committed Aug 6, 2014
1 parent b7c67a4 commit 64a3408
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 38 deletions.
2 changes: 2 additions & 0 deletions Changes
Expand Up @@ -4,6 +4,8 @@
- Added if_none_match method to Mojo::Headers.
- Added is_fresh method to Mojolicious::Static.
- Added is_fresh helper to Mojolicious::Plugin::DefaultHelpers.
- Improved Mojolicious to use MyApp::Controller namespace by default and
encourage its use in the documentation.
- Improved sort method in Mojo::Collection to use $a and $b. (batman)
- Improved Mojolicious::Static to support ETag and If-None-Match headers.
- Improved documentation browser CSS.
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojolicious.pm
Expand Up @@ -154,8 +154,8 @@ sub new {
push @{$self->renderer->paths}, $home->rel_dir('templates');
push @{$self->static->paths}, $home->rel_dir('public');

# Default to application namespace
my $r = $self->routes->namespaces([ref $self]);
# Default to controller and application namespace
my $r = $self->routes->namespaces(["@{[ref $self]}::Controller", ref $self]);

# Hide controller attributes/methods and "handler"
$r->hide(qw(app continue cookie finish flash handler match on param));
Expand Down Expand Up @@ -220,7 +220,7 @@ Mojolicious - Real-time web framework
}
# Controller
package MyApp::Foo;
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';
# Action
Expand Down Expand Up @@ -457,7 +457,7 @@ startup method to define the url endpoints for your application.
$r->post('/baz')->to('test#baz');
# Add another namespace to load controllers from
push @{$app->routes->namespaces}, 'MyApp::Controller';
push @{$app->routes->namespaces}, 'MyApp::C';
=head2 secrets
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Command/generate/app.pm
Expand Up @@ -26,7 +26,7 @@ EOF
$self->render_to_rel_file('appclass', "$name/lib/$app", $class);

# Controller
my $controller = "${class}::Example";
my $controller = "${class}::Controller::Example";
my $path = class_to_path $controller;
$self->render_to_rel_file('controller', "$name/lib/$path", $controller);

Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Controller.pm
Expand Up @@ -439,7 +439,7 @@ Mojolicious::Controller - Controller base class
=head1 SYNOPSIS
# Controller
package MyApp::Foo;
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';
# Action
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojolicious/Guides/Growing.pod
Expand Up @@ -578,14 +578,14 @@ allow running tests again.
Hybrid routes are a nice intermediate step, but to maximize maintainability it
makes sense to split our action code from its routing information.

$ mkdir lib/MyApp
$ touch lib/MyApp/Login.pm
$ chmod 644 lib/MyApp/Login.pm
$ mkdir -p lib/MyApp/Controller
$ touch lib/MyApp/Controller/Login.pm
$ chmod 644 lib/MyApp/Controller/Login.pm

Once again the actual action code does not need to change, we just rename
C<$c> to C<$self> since the controller is now the invocant.

package MyApp::Login;
package MyApp::Controller::Login;
use Mojo::Base 'Mojolicious::Controller';

sub index {
Expand Down
41 changes: 21 additions & 20 deletions lib/Mojolicious/Guides/Routing.pod
Expand Up @@ -169,11 +169,11 @@ defined.

1;

The minimal route above will load and instantiate the class C<MyApp::Foo> and
call its C<welcome> method.
The minimal route above will load and instantiate the class
C<MyApp::Controller::Foo> and call its C<welcome> method.

# Controller
package MyApp::Foo;
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';

# Action
Expand Down Expand Up @@ -259,9 +259,9 @@ old ones.
When the dispatcher sees C<controller> and C<action> values in the stash it
will always try to turn them into a class and method to dispatch to. The
C<controller> value gets camelized using L<Mojo::Util/"camelize"> and
prefixed with a C<namespace> (defaulting to the applications class). While the
action value is not changed at all, because of this both values are case
sensitive.
prefixed with a C<namespace> (defaulting to the applications class followed by
C<::Controller>). While the action value is not changed at all, because of
this both values are case sensitive.

# Application
package MyApp;
Expand All @@ -270,14 +270,15 @@ sensitive.
sub startup {
my $self = shift;

# /bye -> {controller => 'foo', action => 'bye'} -> MyApp::Foo->bye
# /bye -> {controller => 'foo', action => 'bye'}
# -> MyApp::Controller::Foo->bye
$self->routes->route('/bye')->to(controller => 'foo', action => 'bye');
}

1;

# Controller
package MyApp::Foo;
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';

# Action
Expand All @@ -301,7 +302,8 @@ C<controller#action>.
During camelization C<-> gets replaced with C<::>, this allows multi-level
C<controller> hierarchies.

# / -> {controller => 'foo-bar', action => 'hi'} -> MyApp::Foo::Bar->hi
# / -> {controller => 'foo-bar', action => 'hi'}
# -> MyApp::Controller::Foo::Bar->hi
$r->route('/')->to('foo-bar#hi');

For security reasons the dispatcher will always check if the C<controller> is
Expand All @@ -313,22 +315,21 @@ dispatching to it.
You can use the C<namespace> stash value to change the namespace of a whole
route with all its children.

# /bye -> MyApp::Controller::Foo::Bar->bye
$r->route('/bye')
->to(namespace => 'MyApp::Controller::Foo::Bar', action => 'bye');
# /bye -> MyApp::C::Foo::Bar->bye
$r->route('/bye')->to(namespace => 'MyApp::C::Foo::Bar', action => 'bye');

The C<controller> is always appended to the C<namespace> if available.

# /bye -> MyApp::Controller::Foo::Bar->bye
$r->route('/bye')->to('foo-bar#bye', namespace => 'MyApp::Controller');
# /bye -> MyApp::C::Foo::Bar->bye
$r->route('/bye')->to('foo-bar#bye', namespace => 'MyApp::C');

# /hey -> MyApp::Controller::Foo::Bar->hey
$r->route('/hey')->to('Foo::Bar#hey', namespace => 'MyApp::Controller');
# /hey -> MyApp::C::Foo::Bar->hey
$r->route('/hey')->to('Foo::Bar#hey', namespace => 'MyApp::C');

You can also change the default namespaces for all routes in the application
with the router attribute L<Mojolicious::Routes/"namespaces">.

$r->namespaces(['MyApp::Controller']);
$r->namespaces(['MyApp::C']);

=head2 Route to callback

Expand Down Expand Up @@ -533,7 +534,7 @@ additional information.
$r->websocket('/echo')->to(controller => 'foo', action => 'echo');

# Controller
package MyApp::Foo;
package MyApp::Controller::Foo;
use Mojo::Base 'Mojolicious::Controller';

# Action
Expand Down Expand Up @@ -912,7 +913,7 @@ controller. This allows for example the use of the L<Mojolicious::Lite> domain
specific language in normal L<Mojolicious> controllers.

# Controller
package MyApp::Bar;
package MyApp::Controller::Bar;
use Mojolicious::Lite;

# /hello
Expand All @@ -935,7 +936,7 @@ path will be passed along in the C<path> stash value.
A minimal embeddable application is nothing more than a subclass of L<Mojo>,
containing a C<handler> method accepting L<Mojolicious::Controller> objects.

package MyApp::Bar;
package MyApp::Controller::Bar;
use Mojo::Base 'Mojo';

sub handler {
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Renderer.pm
Expand Up @@ -252,7 +252,7 @@ Mojolicious::Renderer - Generate dynamic content
use Mojolicious::Renderer;
my $renderer = Mojolicious::Renderer->new;
push @{$renderer->classes}, 'MyApp::Foo';
push @{$renderer->classes}, 'MyApp::Controller::Foo';
push @{$renderer->paths}, '/home/sri/templates';
=head1 DESCRIPTION
Expand Down
9 changes: 3 additions & 6 deletions lib/Mojolicious/Routes.pm
Expand Up @@ -144,11 +144,8 @@ sub _class {
for my $class (@classes) {

# Failed
unless (my $found = $self->_load($class)) {
next unless defined $found;
$log->debug(qq{Class "$class" is not a controller.});
return undef;
}
next unless defined(my $found = $self->_load($class));
return !$log->debug(qq{Class "$class" is not a controller.}) unless $found;

# Success
my $new = $class->new(%$c);
Expand Down Expand Up @@ -288,7 +285,7 @@ C<attr>, C<has>, C<new> and C<tap>.
Namespaces to load controllers from.
# Add another namespace to load controllers from
push @{$r->namespaces}, 'MyApp::Controller';
push @{$r->namespaces}, 'MyApp::C';
=head2 shortcuts
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Static.pm
Expand Up @@ -151,7 +151,7 @@ Mojolicious::Static - Serve static files
use Mojolicious::Static;
my $static = Mojolicious::Static->new;
push @{$static->classes}, 'MyApp::Foo';
push @{$static->classes}, 'MyApp::Controller::Foo';
push @{$static->paths}, '/home/sri/public';
=head1 DESCRIPTION
Expand Down
4 changes: 4 additions & 0 deletions t/mojolicious/production_app.t
Expand Up @@ -35,6 +35,10 @@ is $t->app->static->file('hello.txt')->slurp,
"Hello Mojo from a static file!\n", 'right content';
is $t->app->moniker, 'mojolicious_test', 'right moniker';

# Default namespaces
is_deeply $t->app->routes->namespaces,
['MojoliciousTest::Controller', 'MojoliciousTest'], 'right namespaces';

# Plugin::Test::SomePlugin2::register (security violation)
$t->get_ok('/plugin-test-some_plugin2/register')->status_isnt(500)
->status_is(404)->header_is(Server => 'Mojolicious (Perl)')
Expand Down

0 comments on commit 64a3408

Please sign in to comment.