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'};