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