goaltools / goal

Goal is a toolkit for high productivity web development in Go language in the spirit of Revel Framework that is built around the concept of code generation.
BSD 2-Clause "Simplified" License
87 stars 3 forks source link

Routes generation #39

Closed ghost closed 8 years ago

ghost commented 8 years ago

Routes in Goal

Goal's routes package in the auto generated skeleton app is nothing more than a global List variable and calls to the default router:

var List = r.Routes{
    r.Get("/some/path", h.SomeController.SomeAction),
    r.Post(...),
    ...
}

Use annotation like syntax. E.g. in Bottle.py there is:

@route('/hello/<name>')
def greet(name):
    return template('<b>Hello {{name}}</b>!', name=name)

There are no annotations in Go, but other tools such as go generate and go build use tags in comments. That's what we can do, too:

//@get /hello/:name
func (c App) Greet(name string) http.Handler {
    c.Context = name
    return c.Render()
}

Import of actions

Controllers end-developer embeds may include actions with routes. Those can be prefixed as follows:

type App struct {
    // ControllerWithErrorMsgActions contains Error404 action
    // with "@get /404".
    pkg.ControllerWithErrorMsgActions `@route:"/errors/"`
}

//
// The code above is equivalent to writing right in this file:
//

//@get /errors/404
func (c *App) Error404() http.Handler {
    ... // Whatever Error404 of ControllerWithErrorMsgActions controller does.
}

Result of generation

It is supposed the generated code will be similar to:

var Routes = []struct{
    Type, Pattern string
    Handler http.Handler
}{
    {Type: "GET", Pattern: "/hello/:name", Handler: h.App.Greet}
    ...
}

This Routes then can be used by the router (after importing the package where it's located).

For now the variable should be located within generated handlers package (as it is easy to implement). After MVP version will require generation of a new routes package in ./assets/.

Reverse routing

We'll use controllers to generate both routes and reverse routes. A new issue must be open for the latter.

ghost commented 8 years ago

This is ready, now we need a new router (or a wrapper around existing router) that would support the generated format.

xpbliss commented 8 years ago

Good! Be quick!

ghost commented 8 years ago

Some early version of routes generation has been implemented. Packages routes and server were removed from the skeleton app.

TODO: add support of custom 404 and 405 errors without use of ugly global variables in the router. I'm thinking about adding an optional third parameter to the route:

//@get    /errors/404    SOME_PARAMETER_HERE
func (c *App) Error404() http.Handler {
    ...
}

We'll use it to let a router know we want this action to be used in case of SOME_PARAMETER_HERE (e.g. error404 or error405).

xpbliss commented 8 years ago

Very good you do ! It is more easy to set the route. By the way, What is the effect on the label of the route? And How to use the SOME_PARAMETER_HERE

ghost commented 8 years ago

I'm working on the next iteration of Goal and rethinking everything. At the moment I'm undecided how far we want to go with the code generation. Do we really need the feature this GH issue introduces? Or do we have to roll back to the routes/routes.go file? I'd like to keep a balance between automation and Go style simplicity / clarity, not turn Goal into something magical. Opinions and thoughts are welcome.