Turf is a library that works with Surf to generate controllers.
The subpackage rest
inside of this repository defines the types of controllers to handle various model types, as defined in Carrot's Restful API Spec.
Base Models are models that can be accessed directly, and are not dependent on the relation of any models.
func NewPostsController() *rest.BaseController {
return &rest.BaseController{
GetModel: func() surf.Model {
return models.NewPost()
},
}
}
Registering this controller enables the following endpoints:
[POST] /posts
[GET] /posts
[GET] /posts/:id
[PUT] /posts/:id
[DELETE] /posts/:id
One to one models are models(a) who exist only to be associated to another model(b), and the model(b) can only reference a single model(a).
func NewPostsVideoController() *rest.OneToOneController {
return &rest.OneToOneController{
NestedModelNameSingular: "video",
ForeignReference: "video_id", // The value in the BaseModel that references the NestedModel
GetBaseModel: func() surf.Model {
return models.NewPost()
},
GetNestedModel: func() surf.Model {
return models.NewVideo()
},
}
}
Registering this controller enables the following endpoints:
[POST] /posts/:id/video
[GET] /posts/:id/video
[PUT] /posts/:id/video
[DELETE] /posts/:id/video
One to many models are models(a) that exist to be associated to another model(b), but model(b) can reference multiple models(a).
func NewAuthorPostsController() *rest.OneToManyController {
return &rest.OneToManyController{
NestedForeignReference: "author_id", // The value in the NestedModel that references the BaseModel
GetBaseModel: func() surf.Model {
return models.NewAuthor()
},
GetNestedModel: func() surf.Model {
return models.NewPost()
},
BelongsTo: func(baseModel, nestedModel surf.Model) bool {
return nestedModel.(*models.Post).AuthorId == baseModel.(*models.Author).Id
},
}
}
Registering this controller enables the following endpoints:
[POST] /authors/:id/posts
[GET] /authors/:id/posts
[GET] /authors/:id/posts/:id
[PUT] /authors/:id/posts/:id
[DELETE] /authors/:id/posts/:id
Many to many models are models who are responsible for associating two other models (model(a) to model(b)). These models can contain additional information about the association, but that is optional.
func NewPostTagsController() *rest.ManyToManyController {
return &rest.ManyToManyController{
BaseModelForeignReference: "post_id", // The BaseModel reference in the RelationModel
NestedModelForeignReference: "tag_id", // The NestedModel reference in the RelationModel
GetBaseModel: func() surf.Model {
return models.NewPost()
},
GetNestedModel: func() surf.Model {
return models.NewTag()
},
GetRelationModel: func() surf.Model {
return models.NewPostTag()
},
}
}
Registering this controller enables the following endpoints:
[POST] /posts/:id/tags/:id
[GET] /posts/:id/tags
[GET] /posts/:id/tags/:id
[PUT] /posts/:id/tags/:id
[DELETE] /posts/:id/tags/:id
All Rest models have a field named LifecycleHooks
that can be set to give control at a certain point in the lifecycle of a method.
Usage is detailed in this file.
All Rest models have a field named MethodWhiteList
that can be set with a slice of strings.
rest.BaseController{
GetModel: func() surf.Model {
return models.NewPost()
},
MethodWhiteList: []string{turf.INDEX, turf.SHOW},
}
If MethodWhiteList
is not set, all supported methods get registered upon calling controller.Register
.
All Controllers have a Register
method that will automatically register the controller to a httprouter.Router.
This also allows middleware to be passed in.
router := httprouter.New()
controllers.NewPostsController().Register(router, middleware.Global)
http.ListenAndServe(":8080", router)