Skip to content

Instantly share code, notes, and snippets.

@jeffdonthemic
Created July 24, 2014 16:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffdonthemic/38ea0fc3dc021b45ae6c to your computer and use it in GitHub Desktop.
Save jeffdonthemic/38ea0fc3dc021b45ae6c to your computer and use it in GitHub Desktop.
Building Go Web Apps Tutorial
github.com/topcoderinc/cribs
<h2>{{.Handle}}'s Crib</h2>
{{ if eq .Type "Youtube" }}
<iframe width="560" height="315" src="//www.youtube.com/embed/{{ .URL }}" frameborder="0" allowfullscreen></iframe>
{{ else if eq .Type "Vimeo" }}
<iframe src="//player.vimeo.com/video/{{ .URL }}" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
{{ else }}
<img src="{{ .URL }}">
{{end}}
<p>{{ .Description }}</p>
// create
heroku create -b https://github.com/kr/heroku-buildpack-go.git my-app
// add the mongolabs addon
heroku addons:add mongolab
// add the envrironment variables for mongolab. see environment.sh
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Topcoder Cribs</title>
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.5.0/pure-min.css">
</head>
<body style="margin: 20px;">
<h1>Topcoder Cribs!</h1>
{{ yield }}
</body>
</html>
<h2>Members' Cribs</h2>
<ul>
{{range .}}
<li><a href="/{{.Handle}}">{{.Handle}}</a></li>
{{ end }}
</ul>
<form class="pure-form pure-form-stacked" style="padding-top:25px" action="/" method="POST">
<fieldset>
<legend>Add Your Crib!</legend>
<label for="handle">Handle</label>
<input id="handle" name="handle" type="text" placeholder="Your handle">
<label for="url">URL</label>
<input id="url" name="url" type="text" placeholder="Complete URL for images or just the ID for videos" style="width: 400px">
<label for="type">Type</label>
<select id="type" name="type">
<option>Image</option>
<option>Youtube</option>
<option>Vimeo</option>
</select>
<label for="description">Description</label>
<textarea id="description" name="description" rows="5" cols="50"></textarea>
<button type="submit" class="pure-button pure-button-primary">Submit</button>
</fieldset>
</form>
web: cribs -port=$PORT
package main
import (
"os"
"github.com/codegangsta/martini"
"github.com/codegangsta/martini-contrib/render"
"github.com/codegangsta/martini-contrib/binding"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
)
// the Crib struct that we can serialize and deserialize into Mongodb
type Crib struct {
Handle string `form:"handle"`
URL string `form:"url"`
Type string `form:"type"`
Description string `form:"description"`
}
/*
the function returns a martini.Handler which is called on each request. We simply clone
the session for each request and close it when the request is complete. The call to c.Map
maps an instance of *mgo.Database to the request context. Then *mgo.Database
is injected into each handler function.
*/
func DB() martini.Handler {
session, err := mgo.Dial(os.Getenv("MONGO_URL")) // mongodb://localhost
if err != nil {
panic(err)
}
return func(c martini.Context) {
s := session.Clone()
c.Map(s.DB(os.Getenv("MONGO_DB"))) // local
defer s.Close()
c.Next()
}
}
// function to return an array of all Cribs from mondodb
func All(db *mgo.Database) []Crib {
var cribs []Crib
db.C("cribs").Find(nil).All(&cribs)
return cribs
}
// function to return a specific Crib by handle
func Fetch(db *mgo.Database, handle string) Crib {
var crib Crib
db.C("cribs").Find(bson.M{"handle": handle}).One(&crib)
return crib
}
func main() {
m := martini.Classic()
// specify the layout to use when rendering HTML
m.Use(render.Renderer(render.Options {
Layout: "layout",
}))
// use the Mongo middleware
m.Use(DB())
// list of all cribs
m.Get("/", func(r render.Render, db *mgo.Database) {
r.HTML(200, "list", All(db))
})
/*
create a new crib the form submission. Contains some martini magic. The call
to binding.Form(Crib{}) parses out form data when the request comes in.
It binds the data to the struct, maps it to the request context and
injects into our next handler function to insert into Mongodb.
*/
m.Post("/", binding.Form(Crib{}), func(crib Crib, r render.Render, db *mgo.Database) {
db.C("cribs").Insert(crib)
r.HTML(200, "list", All(db))
})
// display the crib for a specific user
m.Get("/:handle", func(params martini.Params, r render.Render, db *mgo.Database) {
r.HTML(200, "display", Fetch(db, params["handle"]))
})
m.Run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment