From c6d9d1519e14c4a31b513c23677255293943c212 Mon Sep 17 00:00:00 2001 From: Ravonzz Date: Wed, 5 Jun 2024 20:53:24 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20?= =?UTF-8?q?=D0=B2=D0=B0=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D1=8E=20=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D0=B2=20=D0=BA=D0=BE=D0=BD?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=BB=D0=BB=D0=B5=D1=80=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=B9.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=A3?= =?UTF-8?q?=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5,=20=D0=9F=D1=80?= =?UTF-8?q?=D0=BE=D1=81=D0=BC=D0=BE=D1=82=D1=80=20=D0=B2=D1=81=D0=B5=D1=85?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D0=B8=D1=82?= =?UTF-8?q?=D0=B5=D0=BB=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/manufacturerController.go | 67 ++++++++++++++++++- database/models.go | 2 +- .../Create Manufacturer.bru} | 6 +- .../Manufacturer/Delete Manufacturer.bru | 11 +++ .../Manufacturer/Get All Manufacturers.bru | 11 +++ golang-test/{ => Product}/ProductCreate.bru | 4 +- golang-test/environments/golang-test.bru | 4 ++ libs/libs.go | 29 ++++++++ main.go | 17 ++++- message/message.go | 4 +- migrations/migration.go | 8 ++- validators/validators.go | 33 +++++++++ 12 files changed, 181 insertions(+), 15 deletions(-) rename golang-test/{ManufacturerCreate.bru => Manufacturer/Create Manufacturer.bru} (56%) create mode 100644 golang-test/Manufacturer/Delete Manufacturer.bru create mode 100644 golang-test/Manufacturer/Get All Manufacturers.bru rename golang-test/{ => Product}/ProductCreate.bru (84%) create mode 100644 golang-test/environments/golang-test.bru create mode 100644 libs/libs.go create mode 100644 validators/validators.go diff --git a/controllers/manufacturerController.go b/controllers/manufacturerController.go index c92161e..cb0911a 100644 --- a/controllers/manufacturerController.go +++ b/controllers/manufacturerController.go @@ -2,20 +2,36 @@ package controllers import ( "github.com/gin-gonic/gin" + "github.com/go-playground/validator/v10" "golang-test/database" + "golang-test/libs" "golang-test/message" + "golang-test/validators" "log" ) func CreateManufacturer(c *gin.Context, manufacturer database.Manufacturer) { db := database.Connector() - + validate := validators.Validate response := message.Response{Status: 200} - err := db.Create(&manufacturer).Error + err := validate.Struct(manufacturer) + + if err != nil { + response.Error = libs.GetValidationErrors(err.(validator.ValidationErrors)) + response.Status = 400 + message.SendResponse(c, response) + return + } + + err = db.Create(&manufacturer).Error + if err != nil { log.Println(err.Error()) - response.Error = append(response.Error, err.Error()) + response.Error = gin.H{ + "error": err.Error(), + } + response.Status = 500 message.SendResponse(c, response) return @@ -27,3 +43,48 @@ func CreateManufacturer(c *gin.Context, manufacturer database.Manufacturer) { message.SendResponse(c, response) } + +func DeleteManufacturer(c *gin.Context) { + db := database.Connector() + response := message.Response{Status: 200} + + id := c.Param("id") + + var manufacturer database.Manufacturer + + if db.First(&manufacturer, id).Error != nil { + response.Error = gin.H{ + "error": "Manufacturer with id '" + id + "' not found", + } + response.Status = 404 + message.SendResponse(c, response) + return + } + + db.Delete(&manufacturer, id) + + response.Message = gin.H{ + "message": "Manufacturer deleted", + } + message.SendResponse(c, response) +} + +func GetManufacturers(c *gin.Context) { + + type ManufacturerResponse struct { + ID uint + Name string + } + + db := database.Connector() + response := message.Response{Status: 200} + var manufacturers []ManufacturerResponse + + db.Model(&database.Manufacturer{}).Select("ID", "Name").Scan(&manufacturers) + + response.Message = gin.H{ + "manufacturers": manufacturers, + } + + message.SendResponse(c, response) +} diff --git a/database/models.go b/database/models.go index d506116..0e94c6f 100644 --- a/database/models.go +++ b/database/models.go @@ -4,7 +4,7 @@ import "gorm.io/gorm" type Manufacturer struct { gorm.Model - Name string `gorm:"unique"` + Name string `gorm:"unique" validate:"required,custom_unique=Name"` } type Product struct { diff --git a/golang-test/ManufacturerCreate.bru b/golang-test/Manufacturer/Create Manufacturer.bru similarity index 56% rename from golang-test/ManufacturerCreate.bru rename to golang-test/Manufacturer/Create Manufacturer.bru index 87b3eda..ce33faa 100644 --- a/golang-test/ManufacturerCreate.bru +++ b/golang-test/Manufacturer/Create Manufacturer.bru @@ -1,11 +1,11 @@ meta { - name: ManufacturerCreate + name: Create Manufacturer type: http - seq: 3 + seq: 1 } post { - url: http://localhost:8080/manufacturer + url: {{host}}/manufacturer body: json auth: basic } diff --git a/golang-test/Manufacturer/Delete Manufacturer.bru b/golang-test/Manufacturer/Delete Manufacturer.bru new file mode 100644 index 0000000..824300e --- /dev/null +++ b/golang-test/Manufacturer/Delete Manufacturer.bru @@ -0,0 +1,11 @@ +meta { + name: Delete Manufacturer + type: http + seq: 2 +} + +delete { + url: {{host}}/manufacturer/{{manufacturerID}} + body: none + auth: none +} diff --git a/golang-test/Manufacturer/Get All Manufacturers.bru b/golang-test/Manufacturer/Get All Manufacturers.bru new file mode 100644 index 0000000..6ff7365 --- /dev/null +++ b/golang-test/Manufacturer/Get All Manufacturers.bru @@ -0,0 +1,11 @@ +meta { + name: Get All Manufacturers + type: http + seq: 3 +} + +get { + url: {{host}}/manufacturer + body: none + auth: none +} diff --git a/golang-test/ProductCreate.bru b/golang-test/Product/ProductCreate.bru similarity index 84% rename from golang-test/ProductCreate.bru rename to golang-test/Product/ProductCreate.bru index 893a6d3..57d650f 100644 --- a/golang-test/ProductCreate.bru +++ b/golang-test/Product/ProductCreate.bru @@ -1,11 +1,11 @@ meta { name: ProductCreate type: http - seq: 2 + seq: 1 } post { - url: http://localhost:8080/product + url: {{host}}/product body: json auth: none } diff --git a/golang-test/environments/golang-test.bru b/golang-test/environments/golang-test.bru new file mode 100644 index 0000000..6db2f17 --- /dev/null +++ b/golang-test/environments/golang-test.bru @@ -0,0 +1,4 @@ +vars { + host: http://localhost:8080 + manufacturerID: 3 +} diff --git a/libs/libs.go b/libs/libs.go new file mode 100644 index 0000000..43152db --- /dev/null +++ b/libs/libs.go @@ -0,0 +1,29 @@ +package libs + +import ( + "github.com/gin-gonic/gin" + "github.com/go-playground/validator/v10" + "strings" +) + +func GetValidationErrors(errs validator.ValidationErrors) gin.H { + errors := make(map[string]any) + for _, err := range errs { + errors[err.Field()] = err.Error() + } + + return gin.H{ + "error": errors, + } +} + +func ToSnakeCase(str string) string { + var result []rune + for i, r := range str { + if i > 0 && 'A' <= r && r <= 'Z' { + result = append(result, '_') + } + result = append(result, r) + } + return strings.ToLower(string(result)) +} diff --git a/main.go b/main.go index 3997aac..3add00e 100644 --- a/main.go +++ b/main.go @@ -36,7 +36,18 @@ func main() { controllers.CreateManufacturer(c, manufacturer) }) - r.Run() + r.DELETE("/manufacturer/:id", func(c *gin.Context) { + controllers.DeleteManufacturer(c) + }) + + r.GET("/manufacturer", func(c *gin.Context) { + controllers.GetManufacturers(c) + }) + + err := r.Run() + if err != nil { + return + } defer func() { db := database.Connector() @@ -44,7 +55,9 @@ func main() { if err != nil { log.Fatal(err) } - if err := sqlDB.Close(); err != nil { + + err = sqlDB.Close() + if err != nil { log.Println(err) } }() diff --git a/message/message.go b/message/message.go index 8dc34a6..0498f91 100644 --- a/message/message.go +++ b/message/message.go @@ -7,13 +7,13 @@ import ( type Response struct { Status int Message gin.H - Error []string + Error gin.H } func SendResponse(c *gin.Context, response Response) { if len(response.Message) > 0 { c.JSON(response.Status, response.Message) } else if len(response.Error) > 0 { - c.JSON(response.Status, gin.H{"errors": response.Error}) + c.JSON(response.Status, response.Error) } } diff --git a/migrations/migration.go b/migrations/migration.go index 6d1973a..5c84d1f 100644 --- a/migrations/migration.go +++ b/migrations/migration.go @@ -4,6 +4,7 @@ import ( "golang-test/database" "gorm.io/driver/postgres" "gorm.io/gorm" + "log" ) func main() { @@ -13,8 +14,11 @@ func main() { panic("failed to connect database") } // Migrate the schema - db.AutoMigrate(&database.Manufacturer{}, &database.Product{}, &database.User{}) - + err = db.AutoMigrate(&database.Manufacturer{}, &database.Product{}, &database.User{}) + if err != nil { + return + } + log.Println("Database migration complete") } //func Test(db *gorm.DB) string { diff --git a/validators/validators.go b/validators/validators.go new file mode 100644 index 0000000..b77cfda --- /dev/null +++ b/validators/validators.go @@ -0,0 +1,33 @@ +package validators + +import ( + "fmt" + "github.com/go-playground/validator/v10" + "golang-test/database" + "golang-test/libs" + "log" +) + +var Validate *validator.Validate + +func init() { + Validate = validator.New() + err := Validate.RegisterValidation("custom_unique", UniqueValidator) + if err != nil { + return + } +} + +func UniqueValidator(fl validator.FieldLevel) bool { + db := database.Connector() + + field := fl.Field().String() + structType := libs.ToSnakeCase(fl.Top().Type().Name()) + "s" + param := fl.Param() + log.Println(field, structType, param) + + var count int64 + db.Table(structType).Where(fmt.Sprintf("%s = ?", param), field).Count(&count) + + return count == 0 +}