Gorm create and return value many2many

Issue

I want to create a data and then return the value, but the value is related to another table.

User response struct

type UserRespone struct {
    ID        int           `json:"id,omitempty"`
    Email     string        `json:"email"`
    FirstName string        `json:"first_name"`
    LastName  string        `json:"last_name"`
    Address   string        `json:"address"`
    Roles     []roles.Roles `json:"roles" gorm:"many2many:users_roles;foreignKey:ID;joinForeignKey:UserID;references:ID;joinReferences:RolesID"`
}

Roles struct

type Roles struct {
    ID   int `json:"id" gorm:"<-:false;primaryKey"`
    Name string
}

And this is a function to create a data, and I want to return the value [ ]roles.Roles

func (r *UserRepositoryImpl) AuthSignUp(ctx context.Context, req user.AuthSignUp) (user.UserRespone, error) {
    createdUser := req.ToUser()
    
    hashPassword, _ := bcrypt.GenerateFromPassword([]byte(createdUser.Password), bcrypt.DefaultCost)

    createdUser.Password = string(hashPassword[:])

    result := r.Db.
        WithContext(ctx).
        Create(&createdUser)

    for _, rolesID := range req.RolesID {
        userRole := new(user.UsersRoles)

        userRole.UserID = createdUser.ID
        userRole.RolesID = rolesID
        result = r.Db.WithContext(ctx).Create(&userRole)
    }

    return createdUser.ToResponse(), result.Error
}

I want to return the value like this:

user.UserResponse{
        ID:        4,
        Email:     "putri4@gmail.com",
        FirstName: "putri",
        LastName:  "cantik",
        Address:   "bonang",
        Roles: []roles.Roles{
            {
                ID: 1,
                Name: "Admin",
            },
            {
                ID: 2,
                Name: "Consumer",
            },
        },
    }

But when I create a data set, I only get values like :

user.UserRespones{
        ID:        4,
        Email:     "putri4@gmail.com",
        FirstName: "putri",
        LastName:  "cantik",
        Address:   "bonang",
        Roles:     []roles.Roles(nil),
    }

Solution

As far as I can tell, you already have the user data and the role ids. I figure you just want to get the role names as well:

err := r.db.Find(&createdUser.Roles, req.RolesID)
// err handling

That said, your types and names are a bit unclear. UserRespone (note the typo) should probably named like DBUser – it isn’t important whether it is used as response or something else, it represents the database entry for an user, right?

Additionally, I can only make assumptions about the type and fields of createdUser and UsersRoles, so I might have missed something.

I figure createdUser is of type UserRespone – but then I would expect that Roles is already complete (and you don’t have to query anything at all). If not, then you should introduce a new type for that, e.g. RequestUser (as opposed to DBUser), which only contains Role ids but not Role names. Squeezing the data from the request, the db entry and the response data into the same type is confusing (and a tad too tightly coupled for my taste).

Answered By – NotX

Answer Checked By – Marie Seifert (GoLangFix Admin)

Leave a Reply

Your email address will not be published.