I made a simple post API to store articles in database using Gorm And Go Gin.
problem with API showing when I tried to post the category name instead of the category id because the struct declaring it as int32 type
I made a simple function to getting the id of the category instead of the name but i don't know how to inject it within the incoming request
The article model
package models
import (
"gorm.io/gorm"
)
type News struct {
Id int `gorm:"primary_key;auto_increment;not_null" json:"id"`
Category int32 `gorm:"category" json:"category" binding:"required"`
CountryID int32 `gorm:"country_id" json:"country_id" binding:"required"`
LangID int32 `gorm:"lang_id" json:"lang_id" binding:"required"`
SourceId int32 `gorm:"source_id" json:"source_id" binding:"required"`
HashtagId int32 `gorm:"hashtag_id" json:"hashtag_id" binding:"required"`
Title string `gorm:"title" json:"title" binding:"required"`
Content string `gorm:"content" json:"content" binding:"required"`
Description string `gorm:"description" json:"description" binding:"required"`
Summery string `gorm:"summery" json:"summery" binding:"required"`
ImageUrl string `gorm:"image_url" json:"image_url" binding:"required"`
SourceUrl string `gorm:"source_url" json:"source_url" binding:"required"`
Author string `gorm:"author" json:"author" `
}
func CreateArticle(db *gorm.DB, article *News) (err error) {
err = db.Create(article).Error
if err != nil {
return err
}
return nil
}
Category Model
package models
import "gorm.io/gorm"
type Category struct {
Id int32 `gorm:"primary_key;auto_increment;not_null" json:"id"`
Name string `gorm:"category_name" json:"category" binding:"required"`
Parent int32 `gorm:"parent" json:"parent"`
}
func GetCategoryByName(db *gorm.DB, category *Category, name string) (err error) {
err = db.Where("LOWER(category_name) Like LOWER(?)", "%"+name+"%").First(category).Error
if err != nil {
return err
}
return nil
}
News Controller which implement the models
package controllers
import (
"errors"
"net/http"
"github.com/fouad82/news-app-go/models"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"gorm.io/gorm"
)
type NewsRepo struct {
db *gorm.DB
}
func NewArticle() *NewsRepo {
db := models.InitDb()
return &NewsRepo{db: db}
}
// CreateArticle Create Article
func (repository *NewsRepo) CreateArticle(c *gin.Context) {
var Category models.Category
if err := c.ShouldBindBodyWith(&Category, binding.JSON); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": "error", "error": &Category})
return
}
err := models.GetCategoryByName(repository.db, &Category, Category.Name)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.AbortWithStatus(http.StatusNotFound)
return
}
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"status": "error", "error": err})
return
}
var CategoryId = Category.Id
var Article models.News
Article.Category = CategoryId
if err := c.ShouldBindBodyWith(&Article, binding.JSON); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"status": "error", "error": err})
return
}
err = models.GetArticleByTitle(repository.db, &Article, Article.Title)
if err == nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.AbortWithStatus(http.StatusNotFound)
return
}
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"status": "error", "error": "Title Created Before"})
return
}
createArticle := models.CreateArticle(repository.db, &Article)
if createArticle != nil {
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"status": "error", "error": createArticle})
return
}
c.JSON(http.StatusOK, gin.H{"status": "ok", "result": "Article Created"})
}
in this line i tried to inject the int value within the article struct abut it still getting error that im passing string value not int and this because it still read from the request json not the injected parameter
var CategoryId = Category.Id
var Article models.News
Article.Category = CategoryId