diff --git a/api/handler.go b/api/handler.go index d5bdaab..86e74be 100644 --- a/api/handler.go +++ b/api/handler.go @@ -69,6 +69,7 @@ func Handler() *mux.Router { m.Get(router.CreateMeasurement).Handler(handler(serveCreateMeasurement)) m.Get(router.Measurements).Handler(handler(serveMeasurementList)) m.Get(router.UpdateMeasurement).Handler(handler(serveUpdateMeasurement)) + m.Get(router.DeleteMeasurement).Handler(handler(serveDeleteMeasurement)) return m } diff --git a/api/measurements.go b/api/measurements.go index 8b179e0..719e520 100644 --- a/api/measurements.go +++ b/api/measurements.go @@ -76,3 +76,17 @@ func serveUpdateMeasurement(w http.ResponseWriter, r *http.Request) error { return writeJSON(w, measurement) } + +func serveDeleteMeasurement(w http.ResponseWriter, r *http.Request) error { + id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) + + deleted, err := store.Measurements.Delete(id) + if err != nil { + return err + } + if deleted { + w.WriteHeader(http.StatusOK) + } + + return writeJSON(w, &models.Measurement{}) +} diff --git a/api/measurements_test.go b/api/measurements_test.go index de02b40..2e6848c 100644 --- a/api/measurements_test.go +++ b/api/measurements_test.go @@ -124,3 +124,30 @@ func TestMeasurement_Update(t *testing.T) { t.Error("!success") } } + +func TestMeasurement_Delete(t *testing.T) { + setup() + + want := newMeasurement() + + calledDelete := false + store.Measurements.(*models.MockMeasurementsService).Delete_ = func(id int64) (bool, error) { + if id != want.Id { + t.Errorf("wanted request for measurement %d but got %d", want.Id, id) + } + calledDelete = true + return true, nil + } + + success, err := apiClient.Measurements.Delete(want.Id) + if err != nil { + t.Fatal(err) + } + + if !calledDelete { + t.Error("!calledDelete") + } + if !success { + t.Error("!success") + } +} diff --git a/datastore/measurements.go b/datastore/measurements.go index ae01cf4..9273493 100644 --- a/datastore/measurements.go +++ b/datastore/measurements.go @@ -69,3 +69,19 @@ func (s *measurementsStore) Update(id int64, measurement *models.Measurement) (b return true, nil } + +func (s *measurementsStore) Delete(id int64) (bool, error) { + measurement, err := s.Get(id) + if err != nil { + return false, err + } + + deleted, err := s.dbh.Delete(measurement) + if err != nil { + return false, err + } + if deleted == 0 { + return false, ErrNoRowsDeleted + } + return true, nil +} diff --git a/datastore/measurements_test.go b/datastore/measurements_test.go index fda3890..1f0c3e4 100644 --- a/datastore/measurements_test.go +++ b/datastore/measurements_test.go @@ -118,3 +118,22 @@ func TestMeasurementsStore_Update_db(t *testing.T) { t.Error("!updated") } } + +func TestMeasurementsStore_Delete_db(t *testing.T) { + tx, _ := DB.Begin() + defer tx.Rollback() + + measurement := insertMeasurement(t, tx) + + d := NewDatastore(tx) + + // Delete it + deleted, err := d.Measurements.Delete(measurement.Id) + if err != nil { + t.Fatal(err) + } + + if !deleted { + t.Error("!delete") + } +} diff --git a/models/measurements.go b/models/measurements.go index 849f209..6381f3e 100644 --- a/models/measurements.go +++ b/models/measurements.go @@ -46,6 +46,9 @@ type MeasurementsService interface { // Update an existing measurement Update(id int64, MeasurementType *Measurement) (bool, error) + + // Delete a measurement + Delete(id int64) (deleted bool, err error) } var ( @@ -142,11 +145,34 @@ func (s *measurementsService) Update(id int64, measurement *Measurement) (bool, return resp.StatusCode == http.StatusOK, nil } +func (s *measurementsService) Delete(id int64) (bool, error) { + strId := strconv.FormatInt(id, 10) + + url, err := s.client.url(router.DeleteMeasurement, 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 measurement *Measurement + resp, err := s.client.Do(req, &measurement) + if err != nil { + return false, err + } + + return resp.StatusCode == http.StatusOK, nil +} + type MockMeasurementsService struct { Get_ func(id int64) (*Measurement, error) List_ func(opt *MeasurementListOptions) ([]*Measurement, error) Create_ func(measurement *Measurement) (bool, error) Update_ func(id int64, measurement *Measurement) (bool, error) + Delete_ func(id int64) (bool, error) } var _ MeasurementsService = &MockMeasurementsService{} @@ -178,3 +204,10 @@ func (s *MockMeasurementsService) Update(id int64, measurement *Measurement) (bo } return s.Update_(id, measurement) } + +func (s *MockMeasurementsService) Delete(id int64) (bool, error) { + if s.Delete_ == nil { + return false, nil + } + return s.Delete_(id) +} diff --git a/models/measurements_test.go b/models/measurements_test.go index 69b14d7..cc61b88 100644 --- a/models/measurements_test.go +++ b/models/measurements_test.go @@ -147,3 +147,32 @@ func TestMeasurementService_Update(t *testing.T) { t.Fatal("!called") } } + +func TestMeasurementService_Delete(t *testing.T) { + setup() + defer teardown() + + want := newMeasurement() + + var called bool + mux.HandleFunc(urlPath(t, router.DeleteMeasurement, 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.Measurements.Delete(want.Id) + if err != nil { + t.Errorf("Measurements.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 3d2a2da..211baa1 100644 --- a/router/api.go +++ b/router/api.go @@ -64,6 +64,7 @@ func API() *mux.Router { m.Path("/measurements/").Methods("POST").Name(CreateMeasurement) m.Path("/measurements/{Id:.+}").Methods("GET").Name(Measurement) m.Path("/measurements/{Id:.+}").Methods("PUT").Name(UpdateMeasurement) + m.Path("/measurements/{Id:.+}").Methods("DELETE").Name(DeleteMeasurement) return m } diff --git a/router/routes.go b/router/routes.go index 3f8d7a7..e2c9076 100644 --- a/router/routes.go +++ b/router/routes.go @@ -51,4 +51,5 @@ const ( CreateMeasurement = "measurements:create" Measurements = "measurements:list" UpdateMeasurement = "measurements:update" + DeleteMeasurement = "measurements:delete" )