route_mappings.go
func (a *App) Resource(p string, r Resource) *App {

	g := a.Group(p)
	p = "/"

	rv := reflect.ValueOf(r)
	if rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}

	rt := rv.Type()
	rname := fmt.Sprintf("%s.%s", rt.PkgPath(), rt.Name()) + ".%s"

	n := strings.TrimSuffix(rt.Name(), "Resource")
	paramName := name.New(n).ParamID().String()

	type paramKeyable interface {
		ParamKey() string
	}

	if pk, ok := r.(paramKeyable); ok {
		paramName = pk.ParamKey()
	}

	spath := path.Join(p, "{"+paramName+"}")
	setFuncKey(r.List, fmt.Sprintf(rname, "List"))
	g.GET(p, r.List)

	if n, ok := r.(newable); ok {
		setFuncKey(n.New, fmt.Sprintf(rname, "New"))
		g.GET(path.Join(p, "new"), n.New)
	}

	setFuncKey(r.Show, fmt.Sprintf(rname, "Show"))
	g.GET(path.Join(spath), r.Show)

	if n, ok := r.(editable); ok {
		setFuncKey(n.Edit, fmt.Sprintf(rname, "Edit"))
		g.GET(path.Join(spath, "edit"), n.Edit)
	}

	setFuncKey(r.Create, fmt.Sprintf(rname, "Create"))
	g.POST(p, r.Create)
	setFuncKey(r.Update, fmt.Sprintf(rname, "Update"))
	g.PUT(path.Join(spath), r.Update)
	setFuncKey(r.Destroy, fmt.Sprintf(rname, "Destroy"))
	g.DELETE(path.Join(spath), r.Destroy)
	g.Prefix = path.Join(g.Prefix, spath)
	return g
}
func (a *App) Resource(p string, r Resource) *App {

	g := a.Group(p)
	p = "/"

	rv := reflect.ValueOf(r)
	if rv.Kind() == reflect.Ptr {
		rv = rv.Elem()
	}

	rt := rv.Type()
	rname := fmt.Sprintf("%s.%s", rt.PkgPath(), rt.Name()) + ".%s"

	n := strings.TrimSuffix(rt.Name(), "Resource")
	paramName := name.New(n).ParamID().String()

	type paramKeyable interface {
		ParamKey() string
	}

	if pk, ok := r.(paramKeyable); ok {
		paramName = pk.ParamKey()
	}

	spath := path.Join(p, "{"+paramName+"}")
	setFuncKey(r.List, fmt.Sprintf(rname, "List"))
	g.GET(p, r.List)

	if n, ok := r.(newable); ok {
		setFuncKey(n.New, fmt.Sprintf(rname, "New"))
		g.GET(path.Join(p, "new"), n.New)
	}

	setFuncKey(r.Show, fmt.Sprintf(rname, "Show"))
	g.GET(path.Join(spath), r.Show)

	if n, ok := r.(editable); ok {
		setFuncKey(n.Edit, fmt.Sprintf(rname, "Edit"))
		g.GET(path.Join(spath, "edit"), n.Edit)
	}

	setFuncKey(r.Create, fmt.Sprintf(rname, "Create"))
	g.POST(p, r.Create)
	setFuncKey(r.Update, fmt.Sprintf(rname, "Update"))
	g.PUT(path.Join(spath), r.Update)
	setFuncKey(r.Destroy, fmt.Sprintf(rname, "Destroy"))
	g.DELETE(path.Join(spath), r.Destroy)
	g.Prefix = path.Join(g.Prefix, spath)
	return g
}
// Resource maps an implementation of the Resource interface
// to the appropriate RESTful mappings. Resource returns the *App
// associated with this group of mappings so you can set middleware, etc...
// on that group, just as if you had used the a.Group functionality.
/*
	a.Resource("/users", &UsersResource{})

	// Is equal to this:

	ur := &UsersResource{}
	g := a.Group("/users")
	g.GET("/", ur.List) // GET /users => ur.List
	g.GET("/new", ur.New) // GET /users/new => ur.New
	g.GET("/{user_id}", ur.Show) // GET /users/{user_id} => ur.Show
	g.GET("/{user_id}/edit", ur.Edit) // GET /users/{user_id}/edit => ur.Edit
	g.POST("/", ur.Create) // POST /users => ur.Create
	g.PUT("/{user_id}", ur.Update) PUT /users/{user_id} => ur.Update
	g.DELETE("/{user_id}", ur.Destroy) DELETE /users/{user_id} => ur.Destroy
*/