Permalink
Browse files

some doc changes

  • Loading branch information...
1 parent 4a81db4 commit 4bb1b06e517059932f8360822fbea39ca4b3e581 Zbigniew Lukasiak committed Sep 11, 2010
Showing with 104 additions and 32 deletions.
  1. +87 −25 lib/WebNano.pm
  2. +17 −7 lib/WebNano/Controller.pm
View
@@ -68,43 +68,101 @@ This document describes WebNano version 0.001
=head1 SYNOPSIS
-See the example in t/lib/MyApp
+in MyApp.pm
-=head1 DESCRIPTION
+ package MyApp;
+ use base 'WebNano';
+ use WebNano::Renderer::TTiny;
+
+ sub new { ... }
-The design goal numer one here is to provide basic functionality that should cover most
-of use cases and a easy way to override it and extend.
-The design goal number two is to delegate as much as possible to specialized
-CPAN modules with minimal hassle.
-The main functionality is simple mapping (dispatching) of HTTP request paths into method
-calls as in the following example:
+in MyApp/Controller.pm
- '/' -> 'MyApp::Controller->index_action()'
- '/page' -> 'MyApp::Controller->page_action()'
- '/Some/Very/long/path' -> 'MyApp::Controller::Some::Very->long_action( 'path' )
+ package MyApp::Controller;
+
+ use base 'WebNano::Controller';
+
+ sub index_action {
+ my $self = shift;
+ return 'This is my home';
+ }
+
+in app.psgi
-The name of the action subroutine needs to end with '_action' postfix or alternatively
-the mapping of the last part of the path to the subroutine name can be provided with
-'url_map' which can be an array of sub names or a hash of mappings (like run_modes
-in CGI::Application).
+ use MyApp;
+ my $app = MyApp->new();
+ $app->psgi_callback;
+
-The examples in 'extensions' show how one can extend this basic dispatching with
-other dispatching 'flavours':
+=head1 DESCRIPTION
-WebDispatchTable shows how to create a DSL for dispatching (ala Dancer):
+A minimalistic WebNano application consists of three parts - the application
+class, at least one controller class and the standard Plack
+L<app.psgi|http://search.cpan.org/~miyagawa/Plack/scripts/plackup> file.
- get '/some_address' => sub { 'This is some_address in web_dispatch table' };
+The application object is instantiated only once and is used to hold all the
+other constand data objects - like connection to the database, a template
+renderer object (if it is too heavy to be created per request) and generally
+stuff that is too heavy to be rebuild with each request. In contrast the
+controller objects are recreated for each request a new.
-CodeAttributesForMeta shows how to add an 'Action' code attribute (ala Catalyst):
+The dispatching implemented by WebNano is simple mapping of HTTP request paths into method
+calls as in the following examples:
- sub index : Action { 'This is the index page' }
+ '/page' -> 'MyApp::Controller->page_action()'
+ '/Some/Very/long/path' -> 'MyApp::Controller::Some::Very->long_action( 'path' )
+
+Additionally if the path ends in '/' then 'index' is added to it - so '/' is
+mapped to 'index_action' and '/SomeController/' is mapped to
+MyApp::SomeController->index_action.
+
+If someone does not like the '_action' postfixes then he can use the
+'url_map' controller attribute which works like the 'run_modes' attribute in
+CGI::Application - that is provides a map for method dispatching:
+
+ $self->url_map( { 'mapped url' => 'mapped_url' } );
+
+or a list of approved methods to be dispached by name:
+
+ $self->url_map( [ 'safe_method' ] );
+
+More advanced dispatching is done by overriding the 'local_dispatch' method in
+the Controller class:
+
+ around 'local_dispatch' => sub {
+ my( $orig, $self, $path) = @_;
+ my( $id, $method, @args ) = split qr{/}, $path;
+ $method ||= 'view';
+ if( $id && $id =~ /^\d+$/ ){
+ my $rs = $self->application->schema->resultset( 'Dvd' );
+ my $record = $rs->find( $id );
+ if( ! $record ) {
+ my $res = $self->request->new_response(404);
+ $res->content_type('text/plain');
+ $res->body( 'No record with id: ' . $id );
+ return $res;
+ }
+ return $self->$method( $record, @args );
+ }
+ return $self->$orig( $path );
+ };
+
+This one checks if the first part of the path is a number - if it is it uses
+it to look for a Dvd object by primary key. If it cannot find such a Dvd then
+it returns a 404. If it finds that dvd it then redispatches by the next path
+part and passes that dvd object as the first parameter to that method call.
-CRUD shows how to create an encapsulated CRUD controller code
+The design goal numer one here is to provide basic functionality that should cover most
+of use cases and a easy way to override it and extend. In general it is easy
+to write your own dispatcher that work for your limited use case - and here
+you just need to do that, you can override the dispatching only for a
+particular controller and you don't need to warry about the general cases.
+
+The example in extensions/WebNano-Controller-DSL/ shows how to create a DSL
+for dispatching (ala Dancer):
-This mapping is done inside Controller code - so it can be easily overridden
-and extended on per directory basis. This should allow one to create
-self-contained controllers that fully encapsulate some specialized functionality.
+ get '/some_address' => sub { 'This is some_address in web_dispatch table' };
=head2 Controller object live in the request scope (new controller per request)
@@ -141,6 +199,10 @@ as input and returns the response.
=head2 renderer
+Nearly every web application uses some templating engine - this is the
+attribute to keep the templating engine object. It is not mandatory that you
+follow this rule.
+
=head1 DIAGNOSTICS
=for author to fill in:
View
@@ -111,21 +111,22 @@ With Moose:
=head1 DESCRIPTION
This is the WebNano base controller. It's handle method dispatches the request
-to appropriate action method.
+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 (their name is mapped literally). 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.
+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
-Dispatches the request to the action methods as described above.
+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.
Should return a Plack::Response object, a string containing the HTML page, a code ref
or undef (which is later interpreted as 404).
@@ -136,7 +137,7 @@ Renders a template.
=head2 local_dispatch
-Finds the method to be called for a path and dispatches to it.
+Finds the method to be called for a given path and dispatches to it.
=head2 request
@@ -145,8 +146,17 @@ Finds the method to be called for a path and dispatches to it.
=head1 ATTRIBUTES
=head2 url_map
+
+A hash that is used as path part to method map.
+
=head2 application
+
+Links back to the application object.
+
=head2 env
+
+L<PSGI environment|http://search.cpan.org/~miyagawa/PSGI/PSGI.pod#The_Environment>
+
=head2 self_url

0 comments on commit 4bb1b06

Please sign in to comment.