Name
Forward::Guides::Routes::Resources - Rails like resource routing for Plack web framework developers (Perl)
Description
Forward::Routes provides support for Rails like resource routing. 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. Framework builders are responsible to load the respective controller classes and to execute the desired controller method. Forward::Routes just generates the routes and in case of a match, provides a match object with the needed controller and action parameters.
# 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
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'};