Get an observation type
This commit is contained in:
		
							parent
							
								
									bedddfdec1
								
							
						
					
					
						commit
						4fd7bf8eba
					
				
					 11 changed files with 271 additions and 13 deletions
				
			
		|  | @ -41,6 +41,8 @@ func Handler() *mux.Router { | ||||||
| 	m.Get(router.UpdateStrain).Handler(handler(serveUpdateStrain)) | 	m.Get(router.UpdateStrain).Handler(handler(serveUpdateStrain)) | ||||||
| 	m.Get(router.DeleteStrain).Handler(handler(serveDeleteStrain)) | 	m.Get(router.DeleteStrain).Handler(handler(serveDeleteStrain)) | ||||||
| 
 | 
 | ||||||
|  | 	m.Get(router.ObservationType).Handler(handler(serveObservationType)) | ||||||
|  | 
 | ||||||
| 	return m | 	return m | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								api/observation_types.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								api/observation_types.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | package api | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"strconv" | ||||||
|  | 
 | ||||||
|  | 	"github.com/gorilla/mux" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func serveObservationType(w http.ResponseWriter, r *http.Request) error { | ||||||
|  | 	id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	observation_type, err := store.ObservationTypes.Get(id) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return writeJSON(w, observation_type) | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								api/observation_types_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								api/observation_types_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | package api | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/thermokarst/bactdb/models" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func newObservationType() *models.ObservationType { | ||||||
|  | 	observation_type := models.NewObservationType() | ||||||
|  | 	return observation_type | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestObservationType_Get(t *testing.T) { | ||||||
|  | 	setup() | ||||||
|  | 
 | ||||||
|  | 	want := newObservationType() | ||||||
|  | 
 | ||||||
|  | 	calledGet := false | ||||||
|  | 
 | ||||||
|  | 	store.ObservationTypes.(*models.MockObservationTypesService).Get_ = func(id int64) (*models.ObservationType, error) { | ||||||
|  | 		if id != want.Id { | ||||||
|  | 			t.Errorf("wanted request for observation_type %d but got %d", want.Id, id) | ||||||
|  | 		} | ||||||
|  | 		calledGet = true | ||||||
|  | 		return want, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	got, err := apiClient.ObservationTypes.Get(want.Id) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !calledGet { | ||||||
|  | 		t.Error("!calledGet") | ||||||
|  | 	} | ||||||
|  | 	if !normalizeDeepEqual(want, got) { | ||||||
|  | 		t.Errorf("got %+v but wanted %+v", got, want) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -13,6 +13,7 @@ type Datastore struct { | ||||||
| 	Genera           models.GeneraService | 	Genera           models.GeneraService | ||||||
| 	Species          models.SpeciesService | 	Species          models.SpeciesService | ||||||
| 	Strains          models.StrainsService | 	Strains          models.StrainsService | ||||||
|  | 	ObservationTypes models.ObservationTypesService | ||||||
| 	dbh              modl.SqlExecutor | 	dbh              modl.SqlExecutor | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -33,6 +34,7 @@ func NewDatastore(dbh modl.SqlExecutor) *Datastore { | ||||||
| 	d.Genera = &generaStore{d} | 	d.Genera = &generaStore{d} | ||||||
| 	d.Species = &speciesStore{d} | 	d.Species = &speciesStore{d} | ||||||
| 	d.Strains = &strainsStore{d} | 	d.Strains = &strainsStore{d} | ||||||
|  | 	d.ObservationTypes = &observationTypesStore{d} | ||||||
| 	return d | 	return d | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -42,5 +44,6 @@ func NewMockDatastore() *Datastore { | ||||||
| 		Genera:           &models.MockGeneraService{}, | 		Genera:           &models.MockGeneraService{}, | ||||||
| 		Species:          &models.MockSpeciesService{}, | 		Species:          &models.MockSpeciesService{}, | ||||||
| 		Strains:          &models.MockStrainsService{}, | 		Strains:          &models.MockStrainsService{}, | ||||||
|  | 		ObservationTypes: &models.MockObservationTypesService{}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								datastore/observation_types.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								datastore/observation_types.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | package datastore | ||||||
|  | 
 | ||||||
|  | import "github.com/thermokarst/bactdb/models" | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	DB.AddTableWithName(models.ObservationType{}, "observation_types").SetKeys(true, "Id") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type observationTypesStore struct { | ||||||
|  | 	*Datastore | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *observationTypesStore) Get(id int64) (*models.ObservationType, error) { | ||||||
|  | 	var observation_type []*models.ObservationType | ||||||
|  | 	if err := s.dbh.Select(&observation_type, `SELECT * FROM observation_types WHERE id=$1;`, id); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if len(observation_type) == 0 { | ||||||
|  | 		return nil, models.ErrObservationTypeNotFound | ||||||
|  | 	} | ||||||
|  | 	return observation_type[0], nil | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								datastore/observation_types_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								datastore/observation_types_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | package datastore | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"reflect" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/jmoiron/modl" | ||||||
|  | 	"github.com/thermokarst/bactdb/models" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func insertObservationType(t *testing.T, tx *modl.Transaction) *models.ObservationType { | ||||||
|  | 	// clean up our target table | ||||||
|  | 	tx.Exec(`DELETE FROM observation_types;`) | ||||||
|  | 	observation_type := newObservationType(t, tx) | ||||||
|  | 	if err := tx.Insert(observation_type); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	return observation_type | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func newObservationType(t *testing.T, tx *modl.Transaction) *models.ObservationType { | ||||||
|  | 	return &models.ObservationType{ObservationTypeName: "Test Obs"} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestObservationTypesStore_Get_db(t *testing.T) { | ||||||
|  | 	tx, _ := DB.Begin() | ||||||
|  | 	defer tx.Rollback() | ||||||
|  | 
 | ||||||
|  | 	want := insertObservationType(t, tx) | ||||||
|  | 
 | ||||||
|  | 	d := NewDatastore(tx) | ||||||
|  | 
 | ||||||
|  | 	observation_type, err := d.ObservationTypes.Get(want.Id) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt) | ||||||
|  | 	normalizeTime(&observation_type.CreatedAt, &observation_type.UpdatedAt, &observation_type.DeletedAt) | ||||||
|  | 
 | ||||||
|  | 	if !reflect.DeepEqual(observation_type, want) { | ||||||
|  | 		t.Errorf("got observation_type %+v, want %+v", observation_type, want) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -20,6 +20,7 @@ type Client struct { | ||||||
| 	Genera           GeneraService | 	Genera           GeneraService | ||||||
| 	Species          SpeciesService | 	Species          SpeciesService | ||||||
| 	Strains          StrainsService | 	Strains          StrainsService | ||||||
|  | 	ObservationTypes ObservationTypesService | ||||||
| 
 | 
 | ||||||
| 	// BaseURL for HTTP requests to bactdb's API. | 	// BaseURL for HTTP requests to bactdb's API. | ||||||
| 	BaseURL *url.URL | 	BaseURL *url.URL | ||||||
|  | @ -51,6 +52,7 @@ func NewClient(httpClient *http.Client) *Client { | ||||||
| 	c.Genera = &generaService{c} | 	c.Genera = &generaService{c} | ||||||
| 	c.Species = &speciesService{c} | 	c.Species = &speciesService{c} | ||||||
| 	c.Strains = &strainsService{c} | 	c.Strains = &strainsService{c} | ||||||
|  | 	c.ObservationTypes = &observationTypesService{c} | ||||||
| 	return c | 	return c | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										73
									
								
								models/observation_types.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								models/observation_types.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | ||||||
|  | package models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"strconv" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"github.com/lib/pq" | ||||||
|  | 	"github.com/thermokarst/bactdb/router" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // An Observation Type is a lookup type | ||||||
|  | type ObservationType struct { | ||||||
|  | 	Id                  int64       `json:"id,omitempty"` | ||||||
|  | 	ObservationTypeName string      `db:"observation_type_name" json:"observation_type_name"` | ||||||
|  | 	CreatedAt           time.Time   `db:"created_at" json:"created_at"` | ||||||
|  | 	UpdatedAt           time.Time   `db:"updated_at" json:"updated_at"` | ||||||
|  | 	DeletedAt           pq.NullTime `db:"deleted_at" json:"deleted_at"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewObservationType() *ObservationType { | ||||||
|  | 	return &ObservationType{ | ||||||
|  | 		ObservationTypeName: "Test Obs Type", | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ObservationTypesService interface { | ||||||
|  | 	// Get an observation type | ||||||
|  | 	Get(id int64) (*ObservationType, error) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	ErrObservationTypeNotFound = errors.New("observation type not found") | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type observationTypesService struct { | ||||||
|  | 	client *Client | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *observationTypesService) Get(id int64) (*ObservationType, error) { | ||||||
|  | 	strId := strconv.FormatInt(id, 10) | ||||||
|  | 
 | ||||||
|  | 	url, err := s.client.url(router.ObservationType, map[string]string{"Id": strId}, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	req, err := s.client.NewRequest("GET", url.String(), nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var observation_type *ObservationType | ||||||
|  | 	_, err = s.client.Do(req, &observation_type) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return observation_type, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type MockObservationTypesService struct { | ||||||
|  | 	Get_ func(id int64) (*ObservationType, error) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var _ ObservationTypesService = &MockObservationTypesService{} | ||||||
|  | 
 | ||||||
|  | func (s *MockObservationTypesService) Get(id int64) (*ObservationType, error) { | ||||||
|  | 	if s.Get_ == nil { | ||||||
|  | 		return nil, nil | ||||||
|  | 	} | ||||||
|  | 	return s.Get_(id) | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								models/observation_types_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								models/observation_types_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | ||||||
|  | package models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 	"reflect" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/thermokarst/bactdb/router" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func newObservationType() *ObservationType { | ||||||
|  | 	observation_type := NewObservationType() | ||||||
|  | 	observation_type.Id = 1 | ||||||
|  | 	return observation_type | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestObservation_TypeService_Get(t *testing.T) { | ||||||
|  | 	setup() | ||||||
|  | 	defer teardown() | ||||||
|  | 
 | ||||||
|  | 	want := newObservationType() | ||||||
|  | 
 | ||||||
|  | 	var called bool | ||||||
|  | 	mux.HandleFunc(urlPath(t, router.ObservationType, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		called = true | ||||||
|  | 		testMethod(t, r, "GET") | ||||||
|  | 
 | ||||||
|  | 		writeJSON(w, want) | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	observation_type, err := client.ObservationTypes.Get(want.Id) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("ObservationTypes.Get returned error: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if !called { | ||||||
|  | 		t.Fatal("!called") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt) | ||||||
|  | 
 | ||||||
|  | 	if !reflect.DeepEqual(observation_type, want) { | ||||||
|  | 		t.Errorf("ObservationTypes.Get return %+v, want %+v", observation_type, want) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -31,5 +31,8 @@ func API() *mux.Router { | ||||||
| 	m.Path("/strains/{Id:.+}").Methods("PUT").Name(UpdateStrain) | 	m.Path("/strains/{Id:.+}").Methods("PUT").Name(UpdateStrain) | ||||||
| 	m.Path("/strains/{Id:.+}").Methods("DELETE").Name(DeleteStrain) | 	m.Path("/strains/{Id:.+}").Methods("DELETE").Name(DeleteStrain) | ||||||
| 
 | 
 | ||||||
|  | 	// ObservationTypes | ||||||
|  | 	m.Path("/observation_types/{Id:.+}").Methods("GET").Name(ObservationType) | ||||||
|  | 
 | ||||||
| 	return m | 	return m | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,4 +22,6 @@ const ( | ||||||
| 	Strains      = "strain:list" | 	Strains      = "strain:list" | ||||||
| 	UpdateStrain = "strain:update" | 	UpdateStrain = "strain:update" | ||||||
| 	DeleteStrain = "strain:delete" | 	DeleteStrain = "strain:delete" | ||||||
|  | 
 | ||||||
|  | 	ObservationType = "observation_type:get" | ||||||
| ) | ) | ||||||
|  |  | ||||||
		Reference in a new issue
	
	 Matthew Dillon
						Matthew Dillon