Customized Join Table Select/Update
apuckey opened this issue · comments
Your Question
Say for example I have these structs:
type Person struct {
ID int
Name string
Addresses []Address `gorm:"many2many:person_addresses;"`
}
type Address struct {
ID uint
Name string
}
type PersonAddress struct {
PersonID int
AddressID int
FieldOne string
FieldTwo string
}
[ ... ]
_ = DB.SetupJoinTable(&Person{}, "Addresses", &PersonAddress{})
My question is:
a) how do I select these custom field out of the join table to get them as JSON when selecting out Person with Preload of Addresses
b) how do I save new values to these, the documentation says you can have custom fields but doesn't explain how to actually do this
The document you expected this should be explained
https://gorm.io/docs/many_to_many.html#Customize-JoinTable
Expected answer
Documentation describing how this could be done?
a) how do I select these custom field out of the join table to get them as JSON when selecting out Person with Preload of Addresses
Preload won't query join table's content, use the join table as has-many to load its value.
b) how do I save new values to these, the documentation says you can have custom fields but doesn't explain how to actually do this
When using many2many, GORM will only create the record with user
, address
's foreign keys, you could add other data in PersonAddress
's before save hooks.
@jinzhu Regarding the point b)
: when I try to insert into projects
it says that the join table has no column roles
, it only creates the key fields although I set a value for this column
package main
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
type User struct {
ID uint
Name string
}
type ProjectUser struct {
UserID uint
ProjectID uint
Roles string
}
func (user *ProjectUser) BeforeSave(db *gorm.DB) error {
user.Roles = "default_val"
return nil
}
type Project struct {
ID uint
Name string
Users []User `gorm:"many2many:project_users;"`
}
func main() {
db, err := gorm.Open(sqlite.Open("test4.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{}, &Project{})
if err := db.SetupJoinTable(&Project{}, "Users", &ProjectUser{}); err != nil {
println(err.Error())
panic("Failed to setup join table")
}
bogdan := User { Name: "Bogdan" }
db.Create(&bogdan)
db.Create(&Project{Name: "Test1", Users: []User {{ID: bogdan.ID}}})
}
go run main.go
2021/08/19 16:32:18 /Users/bahdan.shyshkin/work/gorm_test/main.go:47 table project_users has no column named roles
[0.020ms] [rows:0] INSERT INTO `project_users` (`user_id`,`project_id`,`roles`) VALUES (1,1,"default_val") ON CONFLICT DO NOTHING
2021/08/19 16:32:18 /Users/bahdan.shyshkin/work/gorm_test/main.go:47 table project_users has no column named roles
[0.634ms] [rows:1] INSERT INTO `projects` (`name`) VALUES ("Test1")
@BogdanJava same is happening with me. @jinzhu what can be the issue?
@BogdanJava I've figured it out. Add the SetupJoinTable
method just before Automigrate
.
@BogdanJava I've figured it out. Add the
SetupJoinTable
method just beforeAutomigrate
.
Yes it worked for me, nice solution. Thanks for the help.
@BogdanJava @shreeyashnaik Something I still don't understand... In @BogdanJava's example above, how does one populate the roles
field on the join table with anything other than default_val
, as you can't pass anything to the BeforeCreate
hook?
yea same here, can you provide example, specially on the official documentation, i was even surprised in the first place not finding it