Skip to content

Instantly share code, notes, and snippets.

@kaiobrito
Last active July 8, 2022 14:53
Show Gist options
  • Save kaiobrito/da6bfc26b41ef1be91fa152f742683f8 to your computer and use it in GitHub Desktop.
Save kaiobrito/da6bfc26b41ef1be91fa152f742683f8 to your computer and use it in GitHub Desktop.
Repository blogpost
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/kaiobrito/repository-blogpost/data"
)
type Response[T any] struct {
Data []T `json:"data"`
}
func (app *App) GetTodos(ctx *gin.Context) {
var resp Response[*data.Todo]
resp.Data = []*data.Todo{}
for _, todo := range app.Todos {
resp.Data = append(resp.Data, todo)
}
ctx.JSON(http.StatusOK, resp)
}
func (app *App) GetTodoById(ctx *gin.Context) {
id := ctx.Param("id")
existingTodo := app.Todos[id]
if existingTodo == nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, map[string]string{
"error": "Not found",
})
return
}
ctx.JSON(http.StatusOK, existingTodo)
}
func (app *App) EditTodos(ctx *gin.Context) {
id := ctx.Param("id")
existingTodo := app.Todos[id]
if existingTodo == nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, map[string]string{
"error": "Not found",
})
return
}
var todo data.Todo
err := ctx.BindJSON(&todo)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, map[string]string{
"error": err.Error(),
})
return
}
todo.ID = id
app.Todos[id] = &todo
ctx.JSON(http.StatusOK, todo)
}
func (app *App) CreateTodos(ctx *gin.Context) {
var todo data.Todo
err := ctx.BindJSON(&todo)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, map[string]string{
"error": err.Error(),
})
return
}
app.Todos[todo.ID] = &todo
ctx.JSON(http.StatusOK, todo)
}
func (app *App) GetTodos(ctx *gin.Context) {
todos, err := app.Repo.GetAll(ctx.Request.Context())
// ...
}
func (app *App) GetTodoById(ctx *gin.Context) {
id := ctx.Param("id")
existingTodo, err := app.Repo.GetById(ctx.Request.Context(), id)
// ...
}
func (app *App) EditTodos(ctx *gin.Context) {
id := ctx.Param("id")
_, err := app.Repo.GetById(ctx.Request.Context(), id)
// ...
todo.ID = id
app.Repo.Save(ctx.Request.Context(),todo)
ctx.JSON(http.StatusOK, todo)
}
func (app *App) CreateTodos(ctx *gin.Context) {
// ...
app.Repo.Create(ctx.Request.Context(), todo)
ctx.JSON(http.StatusOK, todo)
}
package repository
type MemoryRepository[Model Identifiable] struct {
IRepository[Model]
Data map[string]*Model
}
func CreateMemoryRepository[Model Identifiable](initialData []Model) IRepository[Model] {
repo := MemoryRepository[Model]{
Data: map[string]*Model{},
}
for _, data := range initialData {
repo.Data[data.GetID()] = &data
}
return &repo
}
func (r MemoryRepository[Model]) GetAll(context.Context) ([]*Model, error) {
models := []*Model{}
for _, data := range r.Data {
models = append(models, data)
}
return models, nil
}
func (r MemoryRepository[Model]) GetById(ctx context.Context, id string) (*Model, error) {
existingTodo := r.Data[id]
if existingTodo == nil {
return nil, NotFound{}
}
return existingTodo, nil
}
func (r MemoryRepository[Model]) Create(ctx context.Context, model Model) error {
r.Data[model.GetID()] = &model
return nil
}
func (r *MemoryRepository[Model]) Save(ctx context.Context, model Model) error {
_, err := r.GetById(model.GetID())
if err != nil {
return err
}
r.Data[model.GetID()] = &model
return nil
}
package repository
import "context"
type Identifiable interface {
GetID() string
}
type IRepository[Model Identifiable] interface {
GetAll(context.Context) ([]*Model, error)
GetById(context.Context, string) (*Model, error)
Create(context.Context, Model) error
Save(context.Context, Model) error
}
package todoapi
type TodoAPIRepository struct {
repository.IRepository[data.Todo]
Token string
}
const (
BASE_URL = "https://api-nodejs-todolist.herokuapp.com/"
)
func CreateTODOAPIRepositoryWithToken(token string) repository.IRepository[data.Todo] {
return TodoAPIRepository{
Token: token,
}
}
func (r TodoAPIRepository) getHeaders() map[string]string {
return map[string]string{
"Authorization": "Bearer " + r.Token,
}
}
func (r TodoAPIRepository) GetAll(context.Context) ([]*data.Todo, error) {
var todos apiResponse[[]apiTodo]
err := request("task", http.MethodGet, nil, r.getHeaders(), &todos)
if err != nil {
return nil, err
}
var results []*data.Todo
for _, todo := range todos.Data {
results = append(results, &data.Todo{
ID: todo.ID,
Name: todo.Name,
Done: todo.Done,
})
}
return results, err
}
func (r TodoAPIRepository) GetById(_ context.Context, id string) (*data.Todo, error) {
var res apiResponse[apiTodo]
err := request("task/"+id, http.MethodGet, nil, r.getHeaders(), &res)
if err != nil {
return nil, err
}
return &data.Todo{
ID: res.Data.ID,
Name: res.Data.Name,
Done: res.Data.Done,
}, err
}
func (r TodoAPIRepository) Create(_ context.Context, todo data.Todo) error {
payload := apiTodo{
ID: "",
Name: todo.Name,
Done: todo.Done,
}
body, err := json.Marshal(payload)
if err != nil {
return err
}
var res apiTodo
err = request("task/", http.MethodPost, bytes.NewBuffer(body), r.getHeaders(), &res)
todo.ID = res.ID
todo.Name = res.Name
todo.Done = res.Done
return err
}
func (r TodoAPIRepository) Save(_ context.Context, todo data.Todo) error {
payload := apiTodo{
Name: todo.Name,
Done: todo.Done,
}
body, err := json.Marshal(payload)
if err != nil {
return err
}
err = request[apiTodo]("task/"+todo.ID, http.MethodPut, bytes.NewBuffer(body), r.getHeaders(), nil)
return err
}
package main
import (
"github.com/gin-gonic/gin"
"github.com/kaiobrito/repository-blogpost/data"
)
type App struct {
Todos map[string]*data.Todo
}
func main() {
app := App{
Todos: map[string]*data.Todo{},
}
r := setupRouter(&app)
r.Run()
}
func setupRouter(app *App) *gin.Engine {
r := gin.Default()
r.GET("todos/", app.GetTodos)
r.GET("todos/:id", app.GetTodoById)
r.POST("todos/:id", app.EditTodos)
r.POST("todos/", app.CreateTodos)
return r
}
package main
type App struct {
Repo repository.IRepository[data.Todo]
}
func main() {
initialData := []data.Todo{}
app := App{
Repo: repository.CreateMemoryRepository(initialData),
}
r := setupRouter(&app)
r.Run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment