diff --git a/api/handler.go b/api/handler.go index 63005cf..1877c31 100644 --- a/api/handler.go +++ b/api/handler.go @@ -39,6 +39,7 @@ func Handler() *mux.Router { m.Get(router.CreateStrain).Handler(handler(serveCreateStrain)) m.Get(router.Strains).Handler(handler(serveStrainList)) m.Get(router.UpdateStrain).Handler(handler(serveUpdateStrain)) + m.Get(router.DeleteStrain).Handler(handler(serveDeleteStrain)) return m } diff --git a/api/strains.go b/api/strains.go index a3bf4e6..d5456d3 100644 --- a/api/strains.go +++ b/api/strains.go @@ -76,3 +76,17 @@ func serveUpdateStrain(w http.ResponseWriter, r *http.Request) error { return writeJSON(w, strain) } + +func serveDeleteStrain(w http.ResponseWriter, r *http.Request) error { + id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) + + deleted, err := store.Strains.Delete(id) + if err != nil { + return err + } + if deleted { + w.WriteHeader(http.StatusOK) + } + + return writeJSON(w, &models.Strain{}) +} diff --git a/api/strains_test.go b/api/strains_test.go index 6b931be..172ec3f 100644 --- a/api/strains_test.go +++ b/api/strains_test.go @@ -126,3 +126,30 @@ func TestStrain_Update(t *testing.T) { t.Error("!success") } } + +func TestStrain_Delete(t *testing.T) { + setup() + + want := newStrain() + + calledDelete := false + store.Strains.(*models.MockStrainsService).Delete_ = func(id int64) (bool, error) { + if id != want.Id { + t.Errorf("wanted request for strain %d but got %d", want.Id, id) + } + calledDelete = true + return true, nil + } + + success, err := apiClient.Strains.Delete(1) + if err != nil { + t.Fatal(err) + } + + if !calledDelete { + t.Error("!calledDelete") + } + if !success { + t.Error("!success") + } +} diff --git a/datastore/strains.go b/datastore/strains.go index d2450e7..13fb331 100644 --- a/datastore/strains.go +++ b/datastore/strains.go @@ -61,3 +61,19 @@ func (s *strainsStore) Update(id int64, strain *models.Strain) (bool, error) { return true, nil } + +func (s *strainsStore) Delete(id int64) (bool, error) { + strain, err := s.Get(id) + if err != nil { + return false, err + } + + deleted, err := s.dbh.Delete(strain) + if err != nil { + return false, err + } + if deleted == 0 { + return false, ErrNoRowsDeleted + } + return true, nil +} diff --git a/datastore/strains_test.go b/datastore/strains_test.go index 2d66773..7209011 100644 --- a/datastore/strains_test.go +++ b/datastore/strains_test.go @@ -107,3 +107,22 @@ func TestStrainsStore_Update_db(t *testing.T) { t.Error("!updated") } } + +func TestStrainsStore_Delete_db(t *testing.T) { + tx, _ := DB.Begin() + defer tx.Rollback() + + strain := insertStrain(t, tx) + + d := NewDatastore(tx) + + // Delete it + deleted, err := d.Strains.Delete(strain.Id) + if err != nil { + t.Fatal(err) + } + + if !deleted { + t.Error("!delete") + } +} diff --git a/models/strains.go b/models/strains.go index c57a56e..e32f98d 100644 --- a/models/strains.go +++ b/models/strains.go @@ -40,6 +40,9 @@ type StrainsService interface { // Update an existing strain Update(id int64, strain *Strain) (updated bool, err error) + + // Delete an existing strain + Delete(id int64) (deleted bool, err error) } var ( @@ -136,11 +139,34 @@ func (s *strainsService) Update(id int64, strain *Strain) (bool, error) { return resp.StatusCode == http.StatusOK, nil } +func (s *strainsService) Delete(id int64) (bool, error) { + strId := strconv.FormatInt(id, 10) + + url, err := s.client.url(router.DeleteStrain, map[string]string{"Id": strId}, nil) + if err != nil { + return false, err + } + + req, err := s.client.NewRequest("DELETE", url.String(), nil) + if err != nil { + return false, err + } + + var strain *Strain + resp, err := s.client.Do(req, &strain) + if err != nil { + return false, err + } + + return resp.StatusCode == http.StatusOK, nil +} + type MockStrainsService struct { Get_ func(id int64) (*Strain, error) List_ func(opt *StrainListOptions) ([]*Strain, error) Create_ func(strain *Strain) (bool, error) Update_ func(id int64, strain *Strain) (bool, error) + Delete_ func(id int64) (bool, error) } var _ StrainsService = &MockStrainsService{} @@ -172,3 +198,10 @@ func (s *MockStrainsService) Update(id int64, strain *Strain) (bool, error) { } return s.Update_(id, strain) } + +func (s *MockStrainsService) Delete(id int64) (bool, error) { + if s.Delete_ == nil { + return false, nil + } + return s.Delete_(id) +} diff --git a/models/strains_test.go b/models/strains_test.go index 6531a05..772e849 100644 --- a/models/strains_test.go +++ b/models/strains_test.go @@ -148,3 +148,32 @@ func TestStrainService_Update(t *testing.T) { t.Fatal("!called") } } + +func TestStrainService_Delete(t *testing.T) { + setup() + defer teardown() + + want := newStrain() + + var called bool + mux.HandleFunc(urlPath(t, router.DeleteStrain, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) { + called = true + testMethod(t, r, "DELETE") + + w.WriteHeader(http.StatusOK) + writeJSON(w, want) + }) + + deleted, err := client.Strains.Delete(want.Id) + if err != nil { + t.Errorf("Strains.Delete returned error: %v", err) + } + + if !deleted { + t.Error("!deleted") + } + + if !called { + t.Fatal("!called") + } +} diff --git a/router/api.go b/router/api.go index 2f27ae3..f879ef6 100644 --- a/router/api.go +++ b/router/api.go @@ -29,6 +29,7 @@ func API() *mux.Router { m.Path("/strains").Methods("POST").Name(CreateStrain) m.Path("/strains/{Id:.+}").Methods("GET").Name(Strain) m.Path("/strains/{Id:.+}").Methods("PUT").Name(UpdateStrain) + m.Path("/strains/{Id:.+}").Methods("DELETE").Name(DeleteStrain) return m } diff --git a/router/routes.go b/router/routes.go index 8658634..68593f7 100644 --- a/router/routes.go +++ b/router/routes.go @@ -21,4 +21,5 @@ const ( CreateStrain = "strain:create" Strains = "strain:list" UpdateStrain = "strain:update" + DeleteStrain = "strain:delete" )