Routing

REST Resources

Generate conventional CRUD routes and resource metadata from a controller.

By Guillermo Alvarez - Published - Updated

Register a resource

Use Resources for conventional CRUD routes:

func Draw(router *lazyroutes.Scope) {
    router.Resources(postcontroller.New)
}

For PostsController, GoLazy derives the plural resource posts, the singular resource post, and the member parameter post_id.

Know the conventional routes

Only actions that exist on the controller are registered:

GET    /posts                 Index
GET    /posts/new             New
POST   /posts                 Create
GET    /posts/{post_id}       Show
GET    /posts/{post_id}/edit  Edit
PATCH  /posts/{post_id}       Update
PUT    /posts/{post_id}       Update
DELETE /posts/{post_id}       Delete

Multiple methods can share a route name, such as post for show, update, and delete.

Customize names and params

Configure a resource with a callback:

router.Resources(postcontroller.New, func(posts *lazyroutes.Resource) {
    posts.Path("articles")
    posts.Singular("article")
    posts.Plural("articles")
    posts.Param("slug")
})

That changes member paths to:

/articles/{slug}

Map models to forms

Forms can target resource routes when a model type is mapped:

router.Resources(cars.New, func(cars *lazyroutes.Resource) {
    cars.Model(Car{})
})

form_for and delete_button_for can then choose create, update, and delete targets without hard-coded paths.

Add custom routes

Collection routes live under the resource path:

router.Resources(postcontroller.New, func(posts *lazyroutes.Resource) {
    posts.Get("search", (*posts.PostsController).Search)
})

Member routes live under the member path:

router.Resources(postcontroller.New, func(posts *lazyroutes.Resource) {
    posts.MemberPatch("publish", (*posts.PostsController).Publish)
})

Those produce routes such as /posts/search and /posts/{post_id}/publish.

Nest resources

Call Resources on a parent resource to nest another REST resource under the parent member path:

router.Resources(postcontroller.New, func(posts *lazyroutes.Resource) {
    posts.Resources(commentcontroller.New)
})

If CommentsController has Create and Show, those actions register:

POST /posts/{post_id}/comments              comments_post
GET  /posts/{post_id}/comments/{comment_id} comment_post

Nested route names end with the parent singular name, so helpers can still distinguish top-level comments from comments that belong to a post.