Skip to content

Commit

Permalink
feat(): adds support for CRUD over libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
aubm committed Mar 26, 2016
0 parents commit ea89b25
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 0 deletions.
31 changes: 31 additions & 0 deletions books.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"net/http"
"time"

"github.com/pborman/uuid"
)

// Book is the representation of a book
type Book struct {
ID uuid.UUID `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Author string `json:"author"`
PublishedDate time.Time `json:"publishedDate"`
}

func getBooks(w http.ResponseWriter, r *http.Request) {
}

func createBook(w http.ResponseWriter, r *http.Request) {
}

func updateBook(w http.ResponseWriter, r *http.Request) {
}

func getOneBook(w http.ResponseWriter, r *http.Request) {
}

func deleteOneBook(w http.ResponseWriter, r *http.Request) {
}
110 changes: 110 additions & 0 deletions libraries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package main

import (
"encoding/json"
"io"
"net/http"

"github.com/gorilla/mux"
"github.com/pborman/uuid"
)

// Library is the representation of a library
type Library struct {
ID string `json:"id" sql:"type:varchar(36);primary key" gorm:"primary_key"`
Name string `json:"name"`
Address string `json:"address"`
Phone string `json:"phone"`
}

func getLibraries(w http.ResponseWriter, r *http.Request) {
var libraries []Library
db.Find(&libraries)
writeJSON(w, libraries)
}

func createLibrary(w http.ResponseWriter, r *http.Request) {
newLibrary, err := libraryFromJSON(r.Body)
if err != nil {
http.Error(w, "Invalid JSON provided", http.StatusBadRequest)
return
}
validationErrs := validateLibrary(*newLibrary)
if len(validationErrs) > 0 {
w.WriteHeader(http.StatusBadRequest)
writeJSON(w, validationErrs)
return
}
newLibrary.ID = uuid.NewUUID().String()
db.Create(newLibrary)
w.Header().Set("Library-Id", newLibrary.ID)
w.WriteHeader(201)
}

func updateLibrary(w http.ResponseWriter, r *http.Request) {
var library Library
requestVars := mux.Vars(r)
db.Where("id = ?", requestVars["libraryId"]).Find(&library)
if library.ID == "" {
http.Error(w, "", http.StatusNotFound)
return
}

update, err := libraryFromJSON(r.Body)
if err != nil {
http.Error(w, "Invalid JSON provided", http.StatusBadRequest)
return
}
library.Name = update.Name
library.Address = update.Address
library.Phone = update.Phone

validationErrs := validateLibrary(library)
if len(validationErrs) > 0 {
w.WriteHeader(http.StatusBadRequest)
writeJSON(w, validationErrs)
return
}

writeJSON(w, library)
}

func getOneLibrary(w http.ResponseWriter, r *http.Request) {
var library Library
requestVars := mux.Vars(r)
db.Where("id = ?", requestVars["libraryId"]).Find(&library)
if library.ID == "" {
http.Error(w, "", http.StatusNotFound)
return
}
writeJSON(w, library)
}

func deleteLibrary(w http.ResponseWriter, r *http.Request) {
requestVars := mux.Vars(r)
db.Where("id = ?", requestVars["libraryId"]).Delete(&Library{})
w.WriteHeader(http.StatusNoContent)
}

func libraryFromJSON(data io.ReadCloser) (*Library, error) {
var library = new(Library)
decoder := json.NewDecoder(data)
err := decoder.Decode(library)
if err != nil {
return nil, err
}
return library, nil
}

func validateLibrary(library Library) (errs []string) {
if library.Name == "" {
errs = append(errs, "The name is required")
}
if library.Address == "" {
errs = append(errs, "The address is required")
}
if library.Phone == "" {
errs = append(errs, "The phone is required")
}
return
}
59 changes: 59 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"sync"

"github.com/gorilla/mux"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)

var db *gorm.DB

func main() {
initDatabase()
defer db.Close()

router := mux.NewRouter()
apiRouter := router.PathPrefix("/api").Subrouter()
apiRouter.HandleFunc("/libraries", getLibraries).Methods("GET")
apiRouter.HandleFunc("/libraries", createLibrary).Methods("POST")
apiRouter.HandleFunc("/libraries/{libraryId}", updateLibrary).Methods("PUT")
apiRouter.HandleFunc("/libraries/{libraryId}", getOneLibrary).Methods("GET")
apiRouter.HandleFunc("/libraries/{libraryId}", deleteLibrary).Methods("DELETE")
apiRouter.HandleFunc("/libraries/{libraryId}/books", getBooks).Methods("GET")
apiRouter.HandleFunc("/libraries/{libraryId}/books", createBook).Methods("GET")
apiRouter.HandleFunc("/libraries/{libraryId}/books/{bookId}", updateBook).Methods("PUT")
apiRouter.HandleFunc("/libraries/{libraryId}/books/{bookId}", getOneBook).Methods("GET")
apiRouter.HandleFunc("/libraries/{libraryId}/books/{bookId}", deleteOneBook).Methods("DELETE")

http.Handle("/", router)
fmt.Println("Application started on port 8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

var initContext sync.Once

func initDatabase() {
initContext.Do(func() {
var err error
db, err = gorm.Open("mysql", "root:root@/books_api?charset=utf8&parseTime=True&loc=Local")
if err != nil {
log.Fatalf("Fail to connect to db: %v", err)
}
})
}

func writeJSON(w http.ResponseWriter, data interface{}) {
bytes, err := json.Marshal(data)
if err != nil {
log.Printf("error while encoding json: %v", err)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(bytes)
}

0 comments on commit ea89b25

Please sign in to comment.