diff --git a/api/handler.go b/api/handler.go index 0e67f60..e128b13 100644 --- a/api/handler.go +++ b/api/handler.go @@ -51,6 +51,7 @@ func Handler() *mux.Router { m.Get(router.CreateObservation).Handler(handler(serveCreateObservation)) m.Get(router.Observations).Handler(handler(serveObservationList)) m.Get(router.UpdateObservation).Handler(handler(serveUpdateObservation)) + m.Get(router.DeleteObservation).Handler(handler(serveDeleteObservation)) return m } diff --git a/api/observations.go b/api/observations.go index 181874e..23ecdce 100644 --- a/api/observations.go +++ b/api/observations.go @@ -76,3 +76,17 @@ func serveUpdateObservation(w http.ResponseWriter, r *http.Request) error { return writeJSON(w, observation) } + +func serveDeleteObservation(w http.ResponseWriter, r *http.Request) error { + id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) + + deleted, err := store.Observations.Delete(id) + if err != nil { + return err + } + if deleted { + w.WriteHeader(http.StatusOK) + } + + return writeJSON(w, &models.Observation{}) +} diff --git a/api/observations_test.go b/api/observations_test.go index 38ce5bb..49425d2 100644 --- a/api/observations_test.go +++ b/api/observations_test.go @@ -124,3 +124,30 @@ func TestObservation_Update(t *testing.T) { t.Error("!success") } } + +func TestObservation_Delete(t *testing.T) { + setup() + + want := newObservation() + + calledDelete := false + store.Observations.(*models.MockObservationsService).Delete_ = func(id int64) (bool, error) { + if id != want.Id { + t.Errorf("wanted request for observation %d but got %d", want.Id, id) + } + calledDelete = true + return true, nil + } + + success, err := apiClient.Observations.Delete(want.Id) + if err != nil { + t.Fatal(err) + } + + if !calledDelete { + t.Error("!calledDelete") + } + if !success { + t.Error("!success") + } +} diff --git a/datastore/observations.go b/datastore/observations.go index 806c834..06cc0a1 100644 --- a/datastore/observations.go +++ b/datastore/observations.go @@ -69,3 +69,19 @@ func (s *observationsStore) Update(id int64, observation *models.Observation) (b return true, nil } + +func (s *observationsStore) Delete(id int64) (bool, error) { + observation, err := s.Get(id) + if err != nil { + return false, err + } + + deleted, err := s.dbh.Delete(observation) + if err != nil { + return false, err + } + if deleted == 0 { + return false, ErrNoRowsDeleted + } + return true, nil +} diff --git a/datastore/observations_test.go b/datastore/observations_test.go index 3d4aa46..428a123 100644 --- a/datastore/observations_test.go +++ b/datastore/observations_test.go @@ -108,3 +108,22 @@ func TestObservationsStore_Update_db(t *testing.T) { t.Error("!updated") } } + +func TestObservationsStore_Delete_db(t *testing.T) { + tx, _ := DB.Begin() + defer tx.Rollback() + + observation := insertObservation(t, tx) + + d := NewDatastore(tx) + + // Delete it + deleted, err := d.Observations.Delete(observation.Id) + if err != nil { + t.Fatal(err) + } + + if !deleted { + t.Error("!delete") + } +} diff --git a/models/observations.go b/models/observations.go index bd9b5ab..753029e 100644 --- a/models/observations.go +++ b/models/observations.go @@ -38,6 +38,9 @@ type ObservationsService interface { // Update an observation Update(id int64, Observation *Observation) (updated bool, err error) + + // Delete an observation + Delete(id int64) (deleted bool, err error) } var ( @@ -134,11 +137,34 @@ func (s *observationsService) Update(id int64, observation *Observation) (bool, return resp.StatusCode == http.StatusOK, nil } +func (s *observationsService) Delete(id int64) (bool, error) { + strId := strconv.FormatInt(id, 10) + + url, err := s.client.url(router.DeleteObservation, 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 observation *Observation + resp, err := s.client.Do(req, &observation) + if err != nil { + return false, err + } + + return resp.StatusCode == http.StatusOK, nil +} + type MockObservationsService struct { Get_ func(id int64) (*Observation, error) List_ func(opt *ObservationListOptions) ([]*Observation, error) Create_ func(observation *Observation) (bool, error) Update_ func(id int64, observation *Observation) (bool, error) + Delete_ func(id int64) (bool, error) } var _ObservationsService = &MockObservationsService{} @@ -170,3 +196,10 @@ func (s *MockObservationsService) Update(id int64, observation *Observation) (bo } return s.Update_(id, observation) } + +func (s *MockObservationsService) Delete(id int64) (bool, error) { + if s.Delete_ == nil { + return false, nil + } + return s.Delete_(id) +} diff --git a/models/observations_test.go b/models/observations_test.go index c5a7fbc..5f4964b 100644 --- a/models/observations_test.go +++ b/models/observations_test.go @@ -143,3 +143,32 @@ func TestObservationService_Update(t *testing.T) { t.Fatal("!called") } } + +func TestObservationService_Delete(t *testing.T) { + setup() + defer teardown() + + want := newObservation() + + var called bool + mux.HandleFunc(urlPath(t, router.DeleteObservation, 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.Observations.Delete(want.Id) + if err != nil { + t.Errorf("Observations.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 0cfe8ad..8e17751 100644 --- a/router/api.go +++ b/router/api.go @@ -43,6 +43,7 @@ func API() *mux.Router { m.Path("/observations").Methods("POST").Name(CreateObservation) m.Path("/observations/{Id:.+}").Methods("GET").Name(Observation) m.Path("/observations/{Id:.+}").Methods("PUT").Name(UpdateObservation) + m.Path("/observations/{Id:.+}").Methods("DELETE").Name(DeleteObservation) return m } diff --git a/router/routes.go b/router/routes.go index 93e8001..fa97b94 100644 --- a/router/routes.go +++ b/router/routes.go @@ -33,4 +33,5 @@ const ( CreateObservation = "observation:create" Observations = "observation:list" UpdateObservation = "observation:update" + DeleteObservation = "observation:delete" )