Permalink
Browse files

DirController; release

  • Loading branch information...
1 parent 063435f commit 1350da7dfb82776653b928bfcc656fb0ad7d616a Zbigniew Lukasiak committed Oct 17, 2010
View
4 Changes
@@ -1,5 +1,5 @@
Revision history for WebNano
-0.001
- Initial release.
+0.001 17-10-2010
+ Initial release.
View
8 dist.ini
@@ -6,10 +6,14 @@ copyright_year = 2010
version = 0.001
[@Basic]
-[AutoPrereq]
-[Prereq]
+[AutoPrereqs]
+[Prereqs]
[TestRelease]
+[MetaNoIndex]
+directory = t/lib
+directory = examples
+directory = extensions
[InstallGuide]
[MetaJSON]
[MetaResources]
View
2 examples/DvdDatabase/lib/DvdDatabase/Controller.pm
@@ -3,7 +3,7 @@ use warnings;
package DvdDatabase::Controller;
-use base 'WebNano::Controller';
+use base 'WebNano::DirController';
sub index_action {
my $self = shift;
View
4 examples/DvdDatabase/lib/DvdDatabase/Controller/DvdSimpleUrl.pm
@@ -47,7 +47,7 @@ sub create_action {
if( $req->method eq 'POST' && $form->process() ){
my $record = $form->item;
my $res = $req->new_response();
- $res->redirect( $self->self_url . 'record/' . $record->id . '/view' );
+ $res->redirect( $self->self_url . $record->id . '/view' );
return $res;
}
$form->field( 'submit' )->value( 'Create' );
@@ -82,7 +82,7 @@ sub edit {
);
if( $req->method eq 'POST' && $form->process() ){
my $res = $req->new_response();
- $res->redirect( $self->self_url . '/' . $record->id . '/view' );
+ $res->redirect( $self->self_url . $record->id . '/view' );
return $res;
}
$form->field( 'submit' )->value( 'Update' );
View
2 examples/DvdDatabase/t/separate_url.t
@@ -20,7 +20,7 @@ for my $controller( qw/Dvd Dvd1 Dvd2/ ){
my $res;
$res = $cb->(GET "/$controller");
like( $res->content, qr/Jurassic Park II/ );
- $res = $cb->(POST "/$controller/record/5/edit", [ name => 'Not Jurassic Park' ] );
+ $res = $cb->(POST "/$controller/record/5/edit", [ name => 'Not Jurassic Park', owner => 1 ] );
ok( $res->is_redirect, 'Redirect after POST' );
$res = $cb->(GET $res->header('Location'));
like( $res->content, qr/Not Jurassic Park/ );
View
3 examples/DvdDatabase/t/simple_url.t
@@ -20,7 +20,8 @@ for my $controller( qw/DvdSimpleUrl/ ){
my $res;
$res = $cb->(GET "/$controller");
like( $res->content, qr/Jurassic Park II/ );
- $res = $cb->(POST "/$controller/5/edit", [ name => 'Not Jurassic Park' ] );
+ $res = $cb->(POST "/$controller/5/edit", [ name => 'Not Jurassic Park', owner => 1 ] );
+ warn $res->content;
ok( $res->is_redirect, 'Redirect after POST' );
$res = $cb->(GET $res->header('Location'));
like( $res->content, qr/Not Jurassic Park/ );
View
6 examples/DvdDatabase/templates/DvdSimpleUrl/list.tt
@@ -16,9 +16,9 @@
<td>
[% record.creation_date %]
</td>
-<td><a href="[% self_url %]record/[% record.id %]/view">View</a></td>
-<td><a href="[% self_url %]record/[% record.id %]/edit">Edit</a></td>
-<td><a href="[% self_url %]record/[% record.id %]/delete">Delete</a></td>
+<td><a href="[% self_url %][% record.id %]/view">View</a></td>
+<td><a href="[% self_url %][% record.id %]/edit">Edit</a></td>
+<td><a href="[% self_url %][% record.id %]/delete">Delete</a></td>
</tr>
[% END %]
</body>
View
2 examples/myapp/MyApp/Controller.pm
@@ -3,7 +3,7 @@ use warnings;
package MyApp::Controller;
-use base 'WebNano::Controller';
+use base 'WebNano::DirController';
sub index_action {
View
2 extensions/WebNano-Controller-DSL/t/lib/MyApp/Controller.pm
@@ -2,7 +2,7 @@ package MyApp::Controller;
use Moose;
use MooseX::NonMoose;
-extends 'WebNano::Controller';
+extends 'WebNano::DirController';
has 'url_map' => ( is => 'ro', default => sub { { 'mapped url' => 'mapped_url' } } );
View
2 extensions/WebNano-Controller-WithAttributes/t/lib/MyApp/Controller.pm
@@ -2,7 +2,7 @@ package MyApp::Controller;
use Moose;
use MooseX::NonMoose;
-extends 'WebNano::Controller';
+extends 'WebNano::DirController';
has 'url_map' => ( is => 'ro', default => sub { { 'mapped url' => 'mapped_url' } } );
View
30 lib/WebNano.pm
@@ -3,13 +3,12 @@ use warnings;
package WebNano;
-use base 'WebNano::FindController';
+use WebNano::FindController 'find_nested';
our $VERSION = '0.001';
use Plack::Response;
use Scalar::Util qw(blessed);
use Object::Tiny::RW 'renderer';
-use Try::Tiny;
use Encode;
sub psgi_callback {
@@ -25,7 +24,7 @@ sub controller_search_path { [ ref(shift) ] };
sub handle {
my( $self, $env ) = @_;
my $path = $env->{PATH_INFO};
- my $c_class = $self->find_nested( '', $self->controller_search_path );
+ my $c_class = find_nested( '', $self->controller_search_path );
$path =~ s{^/}{};
die 'Cannot find root controller' if !$c_class;
my $out = $c_class->handle(
@@ -107,6 +106,15 @@ calls as in the following examples:
'/page' -> 'MyApp::Controller->page_action()'
'/Some/Very/long/path' -> 'MyApp::Controller::Some::Very->long_action( 'path' )
+The first type of dispatching is done by the plain L<WebNano::Controller> - to get actions
+dispatched to controllers in subdirs you need to subclass L<WebNano::DirController>
+(which is also a subclass of C<WebNano::Controller>).
+So your root controllers should usually start with C<use base 'WebNano::DirController'>.
+Other controllers also can subclass C<WebNano::DirController> - but if they do
+their own dispatching to sub-controllers then they need to subclass plain C<WebNano::Controller>,
+otherwise this automatic dispatching, sidestepping the custom-made code could become
+a security risk.
+
Additionally if the last part of the path is empty then C<index> is added to it - so C</> is
mapped to C<index_action> and C</SomeController/> is mapped to
C<MyApp::SomeController-E<gt>index_action>.
@@ -294,24 +302,18 @@ follow this rule.
=head1 DIAGNOSTICS
=for author to fill in:
- List every single error and warning message that the module can
- generate (even the ones that will "never happen"), with a full
- explanation of each problem, one or more likely causes, and any
- suggested remedies.
=over
-=item C<< Error message here, perhaps with %s placeholders >>
-
-[Description of error here]
+=back
-=item C<< Another error message here >>
+=head1 SEE ALSO
-[Description of error here]
+L<WebNano::Renderer::TT> - Template Toolkit renderer with template inheritance
-[Et cetera, et cetera]
+L<WebNano::Controller::CRUD> (experimental),
-=back
+L<http://github.com/zby/Nblog> - example blog engine using WebNano
=head1 DEPENDENCIES
View
38 lib/WebNano/Controller.pm
@@ -2,12 +2,10 @@ use strict;
use warnings;
package WebNano::Controller;
-use base 'WebNano::FindController';
use Try::Tiny;
use URI::Escape 'uri_unescape';
use Plack::Request;
-use File::Spec::Functions qw/catfile catdir/;
use Object::Tiny::RW qw/ app env self_url url_map _req /;
@@ -26,29 +24,6 @@ sub render {
return $self->app->renderer->render( c => $self, @_ );
}
-sub _self_path{
- my $self = shift;
- my $path = ref $self;
- $path =~ s/.*::Controller(?=(::|$))//;
- $path =~ s{::}{/};
- return $path . '/';
-}
-
-sub _external_dispatch {
- my ( $self, $path ) = @_;
- my( $path_part, $new_path ) = ( $path =~ qr{^([^/]*)/?(.*)} );
- $path_part =~ s/::|'//g if defined( $path_part );
- return if !length( $path_part );
- my $controller_class = $self->find_nested( $self->_self_path . $path_part, $self->app->controller_search_path );
- return if !$controller_class;
- return $controller_class->handle(
- path => $new_path,
- self_url => $self->self_url . $path_part . '/',
- env => $self->env,
- app => $self->app,
- );
-}
-
sub local_dispatch {
my ( $self, $path, @args ) = @_;
my @parts = split /\//, $path;
@@ -73,15 +48,15 @@ sub handle {
my ( $class, %args ) = @_;
my $path = delete $args{path};
my $self = $class->new( %args );
- my $out = $self->local_dispatch( $path );
- return $out if defined $out;
- return $self->_external_dispatch( $path );
+ return $self->local_dispatch( $path );
};
1;
__END__
+# ABSTRACT: WebNano Controller
+
=head1 SYNOPSIS
With Moose:
@@ -112,17 +87,12 @@ to appropriate action method or to a next controller.
The action method should return a string containing the HTML page,
a Plack::Response object or a code ref.
-If there is no suitable method in the current class, child controller classes
-are tried out. If there is found one that matches the path part then it is
-instantiated with the current psgi env and it's handle method is called.
-
=head1 METHODS
=head2 handle
This is a class method - it receives the arguments, creates the controller
-object and then uses it's L<local_dispatch> method, if that fails it tries to
-find a suitable child controller class and forwards the request to it.
+object and then uses it's L<local_dispatch> method.
Should return a Plack::Response object, a string containing the HTML page, a code ref
or undef (which is later interpreted as 404).
View
9 lib/WebNano/FindController.pm
@@ -2,11 +2,14 @@ use strict;
use warnings;
package WebNano::FindController;
+
+use Exporter 'import';
+our @EXPORT_OK = qw(find_nested);
+
use Try::Tiny;
-use Object::Tiny::RW;
sub find_nested {
- my( $self, $sub_path, $search_path ) = @_;
+ my( $sub_path, $search_path ) = @_;
return if $sub_path =~ /\./;
$sub_path =~ s{/}{::}g;
my @path = @$search_path;
@@ -30,5 +33,7 @@ sub find_nested {
__END__
+# ABSTRACT: Tool for finding controller classes
+
=head2 find_nested
View
2 t/10.main.t
@@ -25,6 +25,8 @@ test_psgi(
like( $res->content, qr/This is the safe_method page/ );
$res = $cb->(GET "NestedController/with_template");
like( $res->content, qr/This is a NestedController page rendered with a template/ );
+ $res = $cb->(GET "NestedController/self_url");
+ like( $res->content, qr{^/NestedController/$}, 'self_url' );
$res = $cb->(GET "NestedController2/some_method");
like( $res->content, qr/This is a method with _action postfix in MyApp::Controller::NestedController2/ );
View
3 t/lib/MyApp/Controller.pm
@@ -3,8 +3,7 @@ use warnings;
package MyApp::Controller;
-use base 'WebNano::Controller';
-
+use base 'WebNano::DirController';
sub new {
my $class = shift;
View
2 t/lib/MyApp/Controller/Deep.pm
@@ -3,6 +3,6 @@ use warnings;
package MyApp::Controller::Deep;
-use base 'WebNano::Controller';
+use base 'WebNano::DirController';
1;
View
2 t/lib/MyApp/Controller/NestedController.pm
@@ -17,5 +17,7 @@ sub some_method_action { 'This is a method with _action postfix' }
sub with_template_action { shift->render( template => 'some_template' ) }
+sub self_url_action { shift->self_url }
+
1;

0 comments on commit 1350da7

Please sign in to comment.