refactors data access layer to use pop ORM for eager loading, adds book titles rented to renters in response body

This commit is contained in:
David Lick
2020-05-31 00:40:32 -04:00
parent a06b4d70ab
commit 28e52a4e08
29 changed files with 732 additions and 287 deletions
+46 -9
View File
@@ -2,13 +2,15 @@ package renter
import (
bookish "github.com/davidlick/bookish/bookish-server"
"github.com/davidlick/bookish/bookish-server/models"
"github.com/gobuffalo/uuid"
)
// Storage defines behavior for interacting with the renter store.
type Storage interface {
ListAll() (rr []bookish.Renter, err error)
FetchDetails(id int) (r bookish.Renter, err error)
New(name string, address string, email string, phoneNumber string) (id int, err error)
ListAll() (rr []models.Renter, err error)
FetchDetails(id string) (r models.Renter, err error)
New(name string, address string, email string, phoneNumber string) (id uuid.UUID, err error)
}
type service struct {
@@ -18,8 +20,8 @@ type service struct {
// Service defines behavior for interacting with the renter service.
type Service interface {
ListRenters() (rr []bookish.Renter, err error)
FetchRenter(id int) (r bookish.Renter, err error)
RegisterRenter(fullName string, address string, email string, phoneNumber string) (id int, err error)
FetchRenter(id string) (r bookish.Renter, err error)
RegisterRenter(fullName string, address string, email string, phoneNumber string) (id uuid.UUID, err error)
}
// NewService creates a new renter service.
@@ -31,15 +33,50 @@ func NewService(s Storage) *service {
// ListRenters returns all renters from the renter store.
func (s *service) ListRenters() (rr []bookish.Renter, err error) {
return s.store.ListAll()
renters, err := s.store.ListAll()
if err != nil {
return nil, err
}
for _, renter := range renters {
r := MutateRenterModel(renter)
rr = append(rr, r)
}
return rr, nil
}
// FetchRenter returns a specific renter from the renter store.
func (s *service) FetchRenter(id int) (r bookish.Renter, err error) {
return s.store.FetchDetails(id)
func (s *service) FetchRenter(id string) (r bookish.Renter, err error) {
renter, err := s.store.FetchDetails(id)
if err != nil {
return r, err
}
r = MutateRenterModel(renter)
return r, nil
}
// RegisterRenter registers a new renter in the renter store.
func (s *service) RegisterRenter(fullName string, address string, email string, phoneNumber string) (id int, err error) {
func (s *service) RegisterRenter(fullName string, address string, email string, phoneNumber string) (id uuid.UUID, err error) {
return s.store.New(fullName, address, email, phoneNumber)
}
// MutateRenterModel is a convenience function to mutate a models.Renter into a bookish.Renter.
func MutateRenterModel(m models.Renter) bookish.Renter {
r := bookish.Renter{}
r.ID = m.ID.String()
r.Name = m.Name
r.Address = m.Address
r.Email = m.Email
r.PhoneNumber = m.PhoneNumber
for _, rental := range m.Rentals {
if !rental.ReturnDate.Valid {
r.Rentals = append(r.Rentals, rental.BookTitle)
}
}
return r
}
+77 -7
View File
@@ -1,11 +1,13 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: ./renter.go
// Source: renter.go
// Package renter is a generated GoMock package.
package renter
import (
bookish_server "github.com/davidlick/bookish/bookish-server"
models "github.com/davidlick/bookish/bookish-server/models"
uuid "github.com/gobuffalo/uuid"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
@@ -34,10 +36,10 @@ func (m *MockStorage) EXPECT() *MockStorageMockRecorder {
}
// ListAll mocks base method
func (m *MockStorage) ListAll() ([]bookish_server.Renter, error) {
func (m *MockStorage) ListAll() ([]models.Renter, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListAll")
ret0, _ := ret[0].([]bookish_server.Renter)
ret0, _ := ret[0].([]models.Renter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -49,10 +51,10 @@ func (mr *MockStorageMockRecorder) ListAll() *gomock.Call {
}
// FetchDetails mocks base method
func (m *MockStorage) FetchDetails(id int) (bookish_server.Renter, error) {
func (m *MockStorage) FetchDetails(id string) (models.Renter, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchDetails", id)
ret0, _ := ret[0].(bookish_server.Renter)
ret0, _ := ret[0].(models.Renter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -64,10 +66,10 @@ func (mr *MockStorageMockRecorder) FetchDetails(id interface{}) *gomock.Call {
}
// New mocks base method
func (m *MockStorage) New(name, address, email, phoneNumber string) (int, error) {
func (m *MockStorage) New(name, address, email, phoneNumber string) (uuid.UUID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "New", name, address, email, phoneNumber)
ret0, _ := ret[0].(int)
ret0, _ := ret[0].(uuid.UUID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -77,3 +79,71 @@ func (mr *MockStorageMockRecorder) New(name, address, email, phoneNumber interfa
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "New", reflect.TypeOf((*MockStorage)(nil).New), name, address, email, phoneNumber)
}
// MockService is a mock of Service interface
type MockService struct {
ctrl *gomock.Controller
recorder *MockServiceMockRecorder
}
// MockServiceMockRecorder is the mock recorder for MockService
type MockServiceMockRecorder struct {
mock *MockService
}
// NewMockService creates a new mock instance
func NewMockService(ctrl *gomock.Controller) *MockService {
mock := &MockService{ctrl: ctrl}
mock.recorder = &MockServiceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockService) EXPECT() *MockServiceMockRecorder {
return m.recorder
}
// ListRenters mocks base method
func (m *MockService) ListRenters() ([]bookish_server.Renter, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListRenters")
ret0, _ := ret[0].([]bookish_server.Renter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListRenters indicates an expected call of ListRenters
func (mr *MockServiceMockRecorder) ListRenters() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListRenters", reflect.TypeOf((*MockService)(nil).ListRenters))
}
// FetchRenter mocks base method
func (m *MockService) FetchRenter(id string) (bookish_server.Renter, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FetchRenter", id)
ret0, _ := ret[0].(bookish_server.Renter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// FetchRenter indicates an expected call of FetchRenter
func (mr *MockServiceMockRecorder) FetchRenter(id interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchRenter", reflect.TypeOf((*MockService)(nil).FetchRenter), id)
}
// RegisterRenter mocks base method
func (m *MockService) RegisterRenter(fullName, address, email, phoneNumber string) (uuid.UUID, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RegisterRenter", fullName, address, email, phoneNumber)
ret0, _ := ret[0].(uuid.UUID)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// RegisterRenter indicates an expected call of RegisterRenter
func (mr *MockServiceMockRecorder) RegisterRenter(fullName, address, email, phoneNumber interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterRenter", reflect.TypeOf((*MockService)(nil).RegisterRenter), fullName, address, email, phoneNumber)
}
+33 -13
View File
@@ -5,6 +5,8 @@ import (
"testing"
bookish "github.com/davidlick/bookish/bookish-server"
"github.com/davidlick/bookish/bookish-server/models"
"github.com/gofrs/uuid"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
@@ -12,12 +14,12 @@ import (
func TestRenter_ListRenters(t *testing.T) {
testCases := []struct {
TestName string
Renters []bookish.Renter
Renters []models.Renter
Error error
}{
{
TestName: "success",
Renters: []bookish.Renter{
Renters: []models.Renter{
{
Name: "John Doe",
Address: "123 Main Way",
@@ -49,7 +51,13 @@ func TestRenter_ListRenters(t *testing.T) {
service := NewService(mockStorage)
renters, err := service.ListRenters()
assert.Equal(t, tc.Renters, renters)
var expectedRenters []bookish.Renter
for _, renter := range tc.Renters {
r := MutateRenterModel(renter)
expectedRenters = append(expectedRenters, r)
}
assert.Equal(t, expectedRenters, renters)
assert.Equal(t, tc.Error, err)
})
}
@@ -59,13 +67,12 @@ func TestRenter_FetchRenter(t *testing.T) {
testCases := []struct {
TestName string
ID int
Renter bookish.Renter
Renter models.Renter
Error error
}{
{
TestName: "success",
ID: 1,
Renter: bookish.Renter{
Renter: models.Renter{
Name: "John Smith",
Address: "123 Main Way",
Email: "john@smith.com",
@@ -74,7 +81,6 @@ func TestRenter_FetchRenter(t *testing.T) {
},
{
TestName: "error",
ID: 1,
Error: errors.New("test error"),
},
}
@@ -84,13 +90,23 @@ func TestRenter_FetchRenter(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
renterId, err := uuid.NewV4()
if err != nil {
t.Error(err)
}
mockStorage := NewMockStorage(ctrl)
mockStorage.EXPECT().FetchDetails(tc.ID).Return(tc.Renter, tc.Error)
mockStorage.EXPECT().FetchDetails(renterId.String()).Return(tc.Renter, tc.Error)
service := NewService(mockStorage)
renter, err := service.FetchRenter(tc.ID)
renter, err := service.FetchRenter(renterId.String())
assert.Equal(t, tc.Renter, renter)
expectedRenter := MutateRenterModel(tc.Renter)
if tc.Error != nil {
renter.ID = "00000000-0000-0000-0000-000000000000"
}
assert.Equal(t, expectedRenter, renter)
assert.Equal(t, tc.Error, err)
})
}
@@ -103,7 +119,6 @@ func TestRenter_RegisterRenter(t *testing.T) {
Address string
Email string
PhoneNumber string
ReturnID int
Error error
}{
{
@@ -116,13 +131,18 @@ func TestRenter_RegisterRenter(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
returnUuid, err := uuid.NewV4()
if err != nil {
t.Error(err)
}
mockStorage := NewMockStorage(ctrl)
mockStorage.EXPECT().New(tc.Name, tc.Address, tc.Email, tc.PhoneNumber).Return(tc.ReturnID, tc.Error)
mockStorage.EXPECT().New(tc.Name, tc.Address, tc.Email, tc.PhoneNumber).Return(returnUuid, tc.Error)
service := NewService(mockStorage)
id, err := service.RegisterRenter(tc.Name, tc.Address, tc.Email, tc.PhoneNumber)
assert.Equal(t, tc.ReturnID, id)
assert.Equal(t, returnUuid, id)
assert.Equal(t, tc.Error, err)
})
}