Tuesday, September 24, 2013

Go (golang), MVC and MongoDB, part 2

Now comes the fun part, the actual code. The first thing we need to do is configure the website. That consists of routes.go and config.go, both in src/gomgoweb. First we'll tackle the routes. Here is that file in full:
routes.go
// routes
package gomgoweb

import (
// "fmt"
"github.com/QLeelulu/goku"
)

// routes
var Routes []*goku.Route = []*goku.Route{
// static file route
&goku.Route{
Name:     "static",
IsStatic: true,
Pattern:  "/static/(.*)",
},
// default controller and action route
&goku.Route{
Name:    "default",
Pattern: "/{controller}/{action}/{id}",
Default: map[string]string{"controller": "home", "action": "index",
"id": "0"},
},
}

This file configures the two kinds of web addresses we'll be using. The "static" route is for things like JPEG files,or, in our case, a CSS file. The "default" route is for the MVC web addresses. As you probably guessed, the Default dictionary determines the home address of the website (/home/index).

Noe for the more difficult part, config.go. This contains the domain name of the website, as well as the site's behavior and global constants. Here is the whole thing:

config.go
// config
package gomgoweb

import (
"github.com/QLeelulu/goku"
"path"
"runtime"
"time"
)

var Config *goku.ServerConfig = &goku.ServerConfig{
Addr:           "localhost:8080",
ReadTimeout:    10 * time.Second,
WriteTimeout:   10 * time.Second,
MaxHeaderBytes: 1 << 20,
StaticPath:     "static",
ViewPath:       "views",
LogLevel:       goku.LOG_LEVEL_LOG,
Debug:          true,
}

const (
DATABASE     = "gomgoweb-8"
BAND_COL     = "bands"
LOCATION_COL = "locations"
GENRE_COL    = "genres"
ALBUM_COL    = "albums"
DATABASE_DSN = "localhost"
)

func init() {
// project root directory
_, filename, _, _ := runtime.Caller(1)
Config.RootDir = path.Dir(filename)
}

You could use just about any string for the database name. "COL" here is short for "collection". In MongoDB, data is first organized into databases, then into collections. "Addr" determines the domain name. In a real life website, this would more likely be a publicly accessed web address. This file also tells Goku where to find the view HTML files, as well as gives a potential alias for the the "static" directory.  

We of course need a main package and entry point. Those are provided by gomgoweb.go, which goes in the project's root directory. Here it is:

gomgoweb.go
// gomgoweb
package main

import (
// "fmt"
"github.com/QLeelulu/goku"
"gomgoweb"
"gomgoweb/controllers"
// "gomgoweb/models"
// "labix.org/v2/mgo/bson"
"log"
)

func main() {
// fmt.Println("Hello World!")
rt := &goku.RouteTable{Routes: gomgoweb.Routes}
middlewares := []goku.Middlewarer{}
s := goku.CreateServer(rt, middlewares, gomgoweb.Config)
goku.Logger().Logln("Server start on", s.Addr)
log.Fatal(s.ListenAndServe())
}

var home = controllers.HomeController
var band = controllers.BandController
var album = controllers.AlbumController

You can safely ignore the commented-out lines. As you can see, the main() function creates the web server in memory and connects it to the files we previously created. You also see that this file establishes the controllers as global variables. The names of those variables can be anything that's legal in Go. I did things this way for the sake of simple explanation. You could have created those variables in the controller files, given them empty ("_") names, and imported the controller package as _ "gomgoweb/controllers", but I think the way I coded it is more intuitive. The ListenAndServe() method is what actually starts the web server up.

At this point, if you left out all mention of controllers, this code would run. However, you wouldn't be able to view the results in your browser. For that, you need a controller and HTML template file. We'll create those soon. In the next installment, we'll get into other global aspects of this project: the CSS and the layout template.  

Monday, September 23, 2013

Go (golang) and MongoDB Example 2 - A Series on Goku (MVC) Websites

Sorry I've been gone for so long. I decided to discontinue the Couchbase series in favor of MongoDB. I'm going to assume you have a working copy of Go and MongoDB. If you don't, you can get those at http://golang.org/ and http://www.mongodb.org/ . You will also need http://bazaar.canonical.com/en/ and Git (http://git-scm.com/ or https://github.com/) to install the necessary Go packages. You can retrieve those packages by issuing the following commands:

go get github.com/QLeelulu/goku

go get labix.org/v2/mgo

You will also need the /data/db path (C:\data\db in Windows) in your root for MongoDB to work.

This website/web server does not need IIS or Apache to run. It basically catalogs a CD collection. I used the LiteIDE (https://code.google.com/p/golangide/downloads/list) environment to write this program. Zeus (http://www.zeusedit.com/go.html) is another possibility, although you have to pay for it after 45 days.

Another piece of housekeeping is the directory tree. You should create a "gomgoweb" directory on your machine, and you'll need the following paths under it (use "\" instead of "/" if you're using Windows):

src/gomgoweb
src/gomgoweb/controllers
src/gomgoweb/models
src/gomgoweb/views/home
src/gomgoweb/views/band
src/gomgoweb/views/album
src/gomgoweb/views/shared
src/gomgoweb/static

If you have any experience with the MVC architecture, this tree should look familiar. Go expects to see all packages other than "main" under a src/<package_name> directory. The last thing you need to do (if they haven't been done for you) is set up the "gopath" environment variable. That should contain a path to your default Go package directory and the root path of this project. In Windows/DOS, that would look like

set gopath=C:\Go\pkg;C:\gomgoweb

Well, you get the idea. In the next installment, we'll get our hands dirty on some code.