Home > other >  gorm : seperate in-database storing model and query sending model
gorm : seperate in-database storing model and query sending model

Time:11-16

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.

  • Related