wip
This commit is contained in:
parent
6142ac93b9
commit
e90f4a1291
@ -3,14 +3,16 @@ package model
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/manyminds/api2go"
|
"github.com/manyminds/api2go"
|
||||||
"github.com/manyminds/api2go/jsonapi"
|
"github.com/manyminds/api2go/jsonapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Car struct {
|
type Car struct {
|
||||||
ID string `json:"-"`
|
ID uint64 `json:"-"`
|
||||||
Brand string `json:"brand"`
|
Brand string `json:"brand"`
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
Price uint64 `json:"price"`
|
Price uint64 `json:"price"`
|
||||||
@ -70,12 +72,16 @@ func newVerifyError(title string, detail string, pointer string) api2go.Error {
|
|||||||
|
|
||||||
// GetID to satisfy jsonapi.MarshalIdentifier interface
|
// GetID to satisfy jsonapi.MarshalIdentifier interface
|
||||||
func (c Car) GetID() string {
|
func (c Car) GetID() string {
|
||||||
return c.ID
|
return fmt.Sprintf("%d", c.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetID to satisfy jsonapi.UnmarshalIdentifier interface
|
// SetID to satisfy jsonapi.UnmarshalIdentifier interface
|
||||||
func (c *Car) SetID(id string) error {
|
func (c *Car) SetID(id string) error {
|
||||||
c.ID = id
|
intID, err := strconv.ParseUint(id, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.ID = intID
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package resource
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
_ "sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"go-jsonapi-example/internal/model"
|
"go-jsonapi-example/internal/model"
|
||||||
@ -19,17 +19,11 @@ type CarResource struct {
|
|||||||
|
|
||||||
// FindAll to satisfy api2go data source interface
|
// FindAll to satisfy api2go data source interface
|
||||||
func (s CarResource) FindAll(r api2go.Request) (api2go.Responder, error) {
|
func (s CarResource) FindAll(r api2go.Request) (api2go.Responder, error) {
|
||||||
cars := s.CarStorage.GetAll()
|
return &Response{Res: s.CarStorage.GetAll()}, nil
|
||||||
result := make([]model.Car, 0, len(cars))
|
|
||||||
|
|
||||||
for _, car := range cars {
|
|
||||||
result = append(result, *car)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Response{Res: result}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PaginatedFindAll can be used to load cars in chunks
|
// PaginatedFindAll can be used to load cars in chunks
|
||||||
|
/*
|
||||||
func (s CarResource) PaginatedFindAll(r api2go.Request) (uint, api2go.Responder, error) {
|
func (s CarResource) PaginatedFindAll(r api2go.Request) (uint, api2go.Responder, error) {
|
||||||
var (
|
var (
|
||||||
result []model.Car
|
result []model.Car
|
||||||
@ -104,10 +98,15 @@ func (s CarResource) PaginatedFindAll(r api2go.Request) (uint, api2go.Responder,
|
|||||||
|
|
||||||
return uint(len(cars)), &Response{Res: result}, nil
|
return uint(len(cars)), &Response{Res: result}, nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// FindOne to satisfy `api2go.DataSource` interface
|
// FindOne to satisfy `api2go.DataSource` interface
|
||||||
func (s CarResource) FindOne(ID string, r api2go.Request) (api2go.Responder, error) {
|
func (s CarResource) FindOne(ID string, r api2go.Request) (api2go.Responder, error) {
|
||||||
car, err := s.CarStorage.GetOne(ID)
|
intID, err := strconv.ParseUint(ID, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return &Response{}, api2go.NewHTTPError(err, err.Error(), http.StatusNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
car, err := s.CarStorage.GetOne(intID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Response{}, api2go.NewHTTPError(err, err.Error(), http.StatusNotFound)
|
return &Response{}, api2go.NewHTTPError(err, err.Error(), http.StatusNotFound)
|
||||||
}
|
}
|
||||||
@ -133,7 +132,10 @@ func (s CarResource) Create(obj interface{}, r api2go.Request) (api2go.Responder
|
|||||||
|
|
||||||
// Delete to satisfy `api2go.DataSource` interface
|
// Delete to satisfy `api2go.DataSource` interface
|
||||||
func (s CarResource) Delete(id string, r api2go.Request) (api2go.Responder, error) {
|
func (s CarResource) Delete(id string, r api2go.Request) (api2go.Responder, error) {
|
||||||
err := s.CarStorage.Delete(id)
|
intID, err := strconv.ParseUint(id, 10, 64)
|
||||||
|
if err == nil {
|
||||||
|
err = s.CarStorage.Delete(intID)
|
||||||
|
}
|
||||||
return &Response{Code: http.StatusNoContent}, err
|
return &Response{Code: http.StatusNoContent}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"go-jsonapi-example/internal/model"
|
"go-jsonapi-example/internal/model"
|
||||||
|
|
||||||
@ -11,36 +12,55 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CarStorage struct {
|
type CarStorage struct {
|
||||||
cars map[string]*model.Car
|
mutex sync.RWMutex
|
||||||
idCount int
|
cars map[uint64]*model.Car
|
||||||
|
idCount uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Cars []model.Car
|
||||||
|
|
||||||
|
func (c Cars) Len() int { return len(c) }
|
||||||
|
func (c Cars) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
|
||||||
|
func (c Cars) Less(i, j int) bool { return c[i].ID < c[j].ID }
|
||||||
|
|
||||||
func NewCarStorage() *CarStorage {
|
func NewCarStorage() *CarStorage {
|
||||||
return &CarStorage{make(map[string]*model.Car), 1}
|
return &CarStorage{cars: make(map[uint64]*model.Car), idCount: 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s CarStorage) GetAll() map[string]*model.Car {
|
func (s CarStorage) GetAll() Cars {
|
||||||
return s.cars
|
s.mutex.RLock()
|
||||||
|
defer s.mutex.RUnlock()
|
||||||
|
result := make(Cars, 0, len(s.cars))
|
||||||
|
for _, car := range s.cars {
|
||||||
|
result = append(result, *car)
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s CarStorage) GetOne(id string) (model.Car, error) {
|
func (s CarStorage) GetOne(id uint64) (model.Car, error) {
|
||||||
user, ok := s.cars[id]
|
s.mutex.RLock()
|
||||||
|
car, ok := s.cars[id]
|
||||||
if ok {
|
if ok {
|
||||||
return *user, nil
|
defer s.mutex.RUnlock()
|
||||||
|
return *car, nil
|
||||||
}
|
}
|
||||||
|
s.mutex.RUnlock()
|
||||||
errMessage := fmt.Sprintf("Car for id %s not found", id)
|
errMessage := fmt.Sprintf("Car for id %s not found", id)
|
||||||
return model.Car{}, api2go.NewHTTPError(errors.New(errMessage), errMessage, http.StatusNotFound)
|
return model.Car{}, api2go.NewHTTPError(errors.New(errMessage), errMessage, http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CarStorage) Insert(c model.Car) string {
|
func (s *CarStorage) Insert(c model.Car) uint64 {
|
||||||
id := fmt.Sprintf("%d", s.idCount)
|
s.mutex.Lock()
|
||||||
c.ID = id
|
defer s.mutex.Unlock()
|
||||||
s.cars[id] = &c
|
c.ID = s.idCount
|
||||||
|
s.cars[s.idCount] = &c
|
||||||
s.idCount++
|
s.idCount++
|
||||||
return id
|
return c.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CarStorage) Delete(id string) error {
|
func (s *CarStorage) Delete(id uint64) error {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
_, exists := s.cars[id]
|
_, exists := s.cars[id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return fmt.Errorf("Car with id %s does not exist", id)
|
return fmt.Errorf("Car with id %s does not exist", id)
|
||||||
@ -51,6 +71,8 @@ func (s *CarStorage) Delete(id string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CarStorage) Update(c model.Car) error {
|
func (s *CarStorage) Update(c model.Car) error {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
_, exists := s.cars[c.ID]
|
_, exists := s.cars[c.ID]
|
||||||
if !exists {
|
if !exists {
|
||||||
return fmt.Errorf("Car with id %s does not exist", c.ID)
|
return fmt.Errorf("Car with id %s does not exist", c.ID)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user