Name

Forward::Guides::Routes::Resources - Rails like resources for Plack web framework developers (Perl)

Description

Forward::Routes enables web framework developers to build Rails like resources with a single command. The add_resources command generates a bunch of routes that can be used to dispatch to a controller's read, create, update and delete actions and to display CRUD related forms:

# Routes root object
my $routes = Forward::Routes->new;

# Add a resource
$routes->add_resources('cities');

# The following routes are generated:

HTTP     Path                 Controller  Action        Route name
request                       parameter   parameter
method          

GET      /cities/new          cities      create_form   cities_create_form
GET      /cities/:id          cities      show          cities_show
GET      /cities/:id/edit     cities      update_form   cities_update_form
GET      /cities/:id/delete   cities      delete_form   cities_delete_form
GET      /cities              cities      index         cities_index
POST     /cities              cities      create        cities_create
PUT      /cities/:id          cities      update        cities_update
DELETE   /cities/:id          cities      delete        cities_delete

Framework builders are responsible for the dispatching process, Forward::Routes just provides a match object with the needed parameters. Each generated route will usually dispatch to a specific method (see action parameter above) which is used to:

Action (method)       Used to

create_form           display a form to create a new item
show                  display an individual item
update_form           display a form to update an existing item
delete_form           display a form to confirm the deletion of an existing item
index                 list all items
create                create a new item
update                update an existing item
delete                delete an existing item

The internal code to generate a resource makes use of nested routes:

my $resource = $routes->add_route('cities');

# get => /cities
$resource->add_route
  ->via('get')
  ->to("cities#index")
  ->name('cities_index');

# post => /cities
$resource->add_route
  ->via('post')
  ->to("cities#create")
  ->name('cities_create');

# get => /cities/new
$resource->add_route('/new')
  ->via('get')
  ->to("cities#create_form")
  ->name('cities_create_form');

# nested route with id placeholder, placeholder can contain everything
# but dots and slashed (constraint)
my $nested = $resource->add_route(':id')
  ->constraints('id' => qr/[^.\/]+/);

# get => /cities/paris
$nested->add_route
  ->via('get')
  ->to("cities#show")
  ->name('cities_show');

# put => /cities/paris
$nested->add_route
  ->via('put')
  ->to("cities#update")
  ->name('cities_update');

# delete => /cities/paris
$nested->add_route
  ->via('delete')
  ->to("cities#delete")
  ->name('cities_delete');

# get => /cities/paris/edit
$nested->add_route('edit')
  ->via('get')
  ->to("cities#update_form")
  ->name('cities_update_form');

# get => /cities/paris/delete
$nested->add_route('delete')
  ->via('get')
  ->to("cities#delete_form")
  ->name('cities_delete_form');

Multiple resources can be created with a single add_resources call:

# Add multiple resources
$routes->add_resources('cities', 'users', 'articles');

# equals
$routes->add_resources('cities'');
$routes->add_resources('users');
$routes->add_resources('articles');    

Resources inherit the file extension of their parent:

# in order to match get => /cities/paris/edit.html

# Routes root object
my $root = Forward::Routes->new;

# Create a parent route with format "html"
$route_with_html_extension = $root->add_route->format('html');

# add a resource on top of parent
$route_with_html_extension->add_resources('cities');

$m = $root->match(get => '/cities/paris/edit.html');
# $m->[0]->params is
#   {controller => 'cities', action => 'cities_update_form',
#    format => 'html'};