What is an efficient way of sending a gorm model, which the model is not the same with a gorm model using to store datas in database ?
This Post
model (struct) is used to store datas in DB.
type Post struct {
gorm.Model
Title string
Body string
}
But I want to use this PostRead
gorm model, to be sent to back to user instead. Since there could be extra variables adding to this later, which won't be store in this database. (or the extra variables could be from another services or databases)
type PostRead struct {
ID string `json:"id" gorm:"primary_key"`
Title string `json:"title"`
Body string `json:"body"`
CreatedAt time.Time `json:"createAt"`
UpdatedAt time.Time `json:"updatedAt"`
...
<other variables to be added later>
}
Here's my current controller codes, to send data back :
func PostGetAll(c *gin.Context) {
posts, err := services.PostGetAllService()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err})
return
}
c.JSON(http.StatusOK, gin.H{"posts": posts})
}
And here's my service codes, to get datas from database :
func PostGetAllService() ([]models.Post, error) {
var posts []models.Post
result := initializers.DB.Find(&posts)
if result.Error != nil {
return nil, errors.New(result.Error.Error())
}
return posts, nil
}
NOTE : I knew that I could create a SliceArray of PostRead
in the controller function PostGetAll()
, then use append()
to add datas from posts (Post
) into the SliceArray.
But for me this seems to be abundant way of solving this problem, hence I wonder if there is a better solution existed ?
Better efficient solution
CodePudding user response:
Not entirely sure of your question but let me try to help anyway.
Normally I would do the following but I am sure there are better ways to do it.
For models I will prepare them in a pkg like the following.
// For reading data from form.
type CreatePostForm struct {
Title string `json:"title"`
Body string `json:"body"`
}
// For interactions with database.
type Post struct {
gorm.Model
Title string
Body string
}
type Posts []Post
// For data transfer object (sending over to UI etc).
type PostDto struct {
Title string
Body string
CreatedDate time.Time
CreatedBy string
}
type PostsDto []PostDto
// Convert form data into database model for database operations.
func (p PostCreateForm) ToCreateModel() (*Post, error) {
// Process logic here which is basically creating a new Post model and returning it..
}
// Convert database model into DTO to reply to request etc.
func (p Post) ToDto() (*PostDto, error) {
// Process logic here which is basically creating a new PostDto model and returning it..
}
// Convert many Posts to many DTOs.
func (ps Posts) ToDto() PostsDto {
dtos := make(PostsDto, len(ps))
for key, post := range ps {
dtos[key] = post.ToDto()
}
return dtos
}
So basically from the above after your get the data from the database you can basically converts type Posts to type PostsDto through the use of methods like Posts.ToDto()
.
The DB adaptor will be in another pkg which basically does the work for reading/writing to the database which I will not share since your question is more of sending another set of data for CRUD operations.
Again, I hope this will help you but I still think there might be a better way to do it.