diff --git a/api/genera.go b/api/genera.go index 3abc161..6d71264 100644 --- a/api/genera.go +++ b/api/genera.go @@ -59,3 +59,22 @@ func serveGenera(w http.ResponseWriter, r *http.Request) error { return writeJSON(w, genera) } + +func serveUpdateGenus(w http.ResponseWriter, r *http.Request) error { + id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) + var genus models.Genus + err := json.NewDecoder(r.Body).Decode(&genus) + if err != nil { + return err + } + + updated, err := store.Genera.Update(id, &genus) + if err != nil { + return err + } + if updated { + w.WriteHeader(http.StatusOK) + } + + return writeJSON(w, genus) +} diff --git a/api/genera_test.go b/api/genera_test.go index d2ab758..d99da53 100644 --- a/api/genera_test.go +++ b/api/genera_test.go @@ -88,3 +88,33 @@ func TestGenus_List(t *testing.T) { t.Errorf("got genera %+v but wanted genera %+v", genera, want) } } + +func TestGenus_Update(t *testing.T) { + setup() + + want := &models.Genus{Id: 1, GenusName: "Test Genus"} + + calledPut := false + store.Genera.(*models.MockGeneraService).Update_ = func(id int64, genus *models.Genus) (bool, error) { + if id != want.Id { + t.Errorf("wanted request for genus %d but got %d", want.Id, id) + } + if !normalizeDeepEqual(want, genus) { + t.Errorf("wanted request for genus %d but got %d", want, genus) + } + calledPut = true + return true, nil + } + + success, err := apiClient.Genera.Update(1, want) + if err != nil { + t.Fatal(err) + } + + if !calledPut { + t.Error("!calledPut") + } + if !success { + t.Error("!success") + } +} diff --git a/api/handler.go b/api/handler.go index 59e1718..e66546f 100644 --- a/api/handler.go +++ b/api/handler.go @@ -26,6 +26,7 @@ func Handler() *mux.Router { m.Get(router.Genus).Handler(handler(serveGenus)) m.Get(router.CreateGenus).Handler(handler(serveCreateGenus)) m.Get(router.Genera).Handler(handler(serveGenera)) + m.Get(router.UpdateGenus).Handler(handler(serveUpdateGenus)) return m } diff --git a/datastore/genera.go b/datastore/genera.go index 260ff07..f492f50 100644 --- a/datastore/genera.go +++ b/datastore/genera.go @@ -45,3 +45,14 @@ func (s *generaStore) List(opt *models.GenusListOptions) ([]*models.Genus, error } return genera, nil } + +func (s *generaStore) Update(id int64, genus *models.Genus) (bool, error) { + ret, err := s.dbh.Exec(`UPDATE genera SET genusname=$1 WHERE id=$2;`, genus.GenusName, id) + if err != nil { + return false, err + } + if rows, err := ret.RowsAffected(); rows == 0 { + return false, err + } + return true, nil +} diff --git a/models/genera.go b/models/genera.go index 2cad177..d6be8ee 100644 --- a/models/genera.go +++ b/models/genera.go @@ -28,6 +28,9 @@ type GeneraService interface { // Create a new genus. The newly created genus's ID is written to genus.Id Create(genus *Genus) (created bool, err error) + + // Update an existing genus. + Update(id int64, genus *Genus) (updated bool, err error) } var ( @@ -105,10 +108,32 @@ func (s *generaService) List(opt *GenusListOptions) ([]*Genus, error) { return genera, nil } +func (s *generaService) Update(id int64, genus *Genus) (bool, error) { + strId := strconv.FormatInt(id, 10) + + url, err := s.client.url(router.UpdateGenus, map[string]string{"Id": strId}, nil) + if err != nil { + return false, err + } + + req, err := s.client.NewRequest("PUT", url.String(), genus) + if err != nil { + return false, err + } + + resp, err := s.client.Do(req, &genus) + if err != nil { + return false, err + } + + return resp.StatusCode == http.StatusOK, nil +} + type MockGeneraService struct { Get_ func(id int64) (*Genus, error) List_ func(opt *GenusListOptions) ([]*Genus, error) - Create_ func(post *Genus) (bool, error) + Create_ func(genus *Genus) (bool, error) + Update_ func(id int64, genus *Genus) (bool, error) } var _ GeneraService = &MockGeneraService{} @@ -133,3 +158,10 @@ func (s *MockGeneraService) List(opt *GenusListOptions) ([]*Genus, error) { } return s.List_(opt) } + +func (s *MockGeneraService) Update(id int64, genus *Genus) (bool, error) { + if s.Update_ == nil { + return false, nil + } + return s.Update_(id, genus) +} diff --git a/models/genera_test.go b/models/genera_test.go index 08269c5..2374a10 100644 --- a/models/genera_test.go +++ b/models/genera_test.go @@ -105,3 +105,34 @@ func TestGeneraService_List(t *testing.T) { t.Errorf("Genera.List return %+v, want %+v", genera, want) } } + +func TestGeneraService_Update(t *testing.T) { + setup() + defer teardown() + + want := &Genus{Id: 1, GenusName: "Test Genus"} + + var called bool + mux.HandleFunc(urlPath(t, router.UpdateGenus, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) { + called = true + testMethod(t, r, "PUT") + testBody(t, r, `{"id":1,"genus_name":"Test Genus Updated","created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","deleted_at":"0001-01-01T00:00:00Z"}`+"\n") + + w.WriteHeader(http.StatusOK) + writeJSON(w, want) + }) + + genus := &Genus{Id: 1, GenusName: "Test Genus Updated"} + updated, err := client.Genera.Update(1, genus) + if err != nil { + t.Errorf("Genera.Update returned error: %v", err) + } + + if !updated { + t.Error("!updated") + } + + if !called { + t.Fatal("!called") + } +} diff --git a/router/api.go b/router/api.go index f545a6e..bf5a396 100644 --- a/router/api.go +++ b/router/api.go @@ -14,5 +14,6 @@ func API() *mux.Router { m.Path("/genera").Methods("GET").Name(Genera) m.Path("/genera").Methods("POST").Name(CreateGenus) m.Path("/genera/{Id:.+}").Methods("GET").Name(Genus) + m.Path("/genera/{Id:.+}").Methods("PUT").Name(UpdateGenus) return m } diff --git a/router/routes.go b/router/routes.go index 4abfa86..ef4d7d8 100644 --- a/router/routes.go +++ b/router/routes.go @@ -1,10 +1,12 @@ package router const ( - User = "user" - CreateUser = "user:create" - Users = "users" + User = "user" + CreateUser = "user:create" + Users = "users" + Genus = "genus" CreateGenus = "genus:create" Genera = "genera" + UpdateGenus = "genus:update" )