Skip to content

Commit

Permalink
Omit associations during Create operations
Browse files Browse the repository at this point in the history
When inserting a new record, GORM will also attempt to
insert records into tables refered to by many-to-many
relationships on the inserted record. This commit
attempts to ensure that associations are omitted
when inserting records, and then the associations
are added to the join tables separately.

Signed-off-by: Sam Lucidi <[email protected]>
  • Loading branch information
mansam committed Jul 18, 2024
1 parent cddd0c8 commit 9fca425
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 14 deletions.
38 changes: 30 additions & 8 deletions api/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,22 @@ func (h ApplicationHandler) AddRoutes(e *gin.Engine) {
routeGroup.DELETE(ApplicationRoot, h.Delete)
// Tags
routeGroup = e.Group("/")
routeGroup.Use(Required("applications"))
routeGroup.Use(Required("applications"), Transaction)
routeGroup.GET(ApplicationTagsRoot, h.TagList)
routeGroup.GET(ApplicationTagsRoot+"/", h.TagList)
routeGroup.POST(ApplicationTagsRoot, h.TagAdd)
routeGroup.DELETE(ApplicationTagRoot, h.TagDelete)
routeGroup.PUT(ApplicationTagsRoot, h.TagReplace, Transaction)
routeGroup.PUT(ApplicationTagsRoot, h.TagReplace)
// Facts
routeGroup = e.Group("/")
routeGroup.Use(Required("applications.facts"))
routeGroup.Use(Required("applications.facts"), Transaction)
routeGroup.GET(ApplicationFactsRoot, h.FactGet)
routeGroup.GET(ApplicationFactsRoot+"/", h.FactGet)
routeGroup.POST(ApplicationFactsRoot, h.FactCreate)
routeGroup.GET(ApplicationFactRoot, h.FactGet)
routeGroup.PUT(ApplicationFactRoot, h.FactPut)
routeGroup.DELETE(ApplicationFactRoot, h.FactDelete)
routeGroup.PUT(ApplicationFactsRoot, h.FactPut, Transaction)
routeGroup.PUT(ApplicationFactsRoot, h.FactPut)
// Bucket
routeGroup = e.Group("/")
routeGroup.Use(Required("applications.bucket"))
Expand All @@ -84,11 +84,11 @@ func (h ApplicationHandler) AddRoutes(e *gin.Engine) {
routeGroup.DELETE(AppBucketContentRoot, h.BucketDelete)
// Stakeholders
routeGroup = e.Group("/")
routeGroup.Use(Required("applications.stakeholders"))
routeGroup.Use(Required("applications.stakeholders"), Transaction)
routeGroup.PUT(AppStakeholdersRoot, h.StakeholdersUpdate)
// Assessments
routeGroup = e.Group("/")
routeGroup.Use(Required("applications.assessments"))
routeGroup.Use(Required("applications.assessments"), Transaction)
routeGroup.GET(AppAssessmentsRoot, h.AssessmentList)
routeGroup.POST(AppAssessmentsRoot, h.AssessmentCreate)
}
Expand Down Expand Up @@ -210,11 +210,23 @@ func (h ApplicationHandler) Create(ctx *gin.Context) {
}
m := r.Model()
m.CreateUser = h.BaseHandler.CurrentUser(ctx)
result := h.DB(ctx).Omit("Tags").Create(m)
result := h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}
db := h.DB(ctx).Model(m)
err = db.Association("Identities").Replace(m.Identities)
if err != nil {
_ = ctx.Error(err)
return
}
db = h.DB(ctx).Model(m)
err = db.Association("Contributors").Replace(m.Contributors)
if err != nil {
_ = ctx.Error(err)
return
}

tags := []model.ApplicationTag{}
if len(r.Tags) > 0 {
Expand Down Expand Up @@ -1078,11 +1090,21 @@ func (h ApplicationHandler) AssessmentCreate(ctx *gin.Context) {
assessment.PrepareForApplication(resolver, application, m)
newAssessment = true
}
result = h.DB(ctx).Create(m)
result = h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}
err = h.DB(ctx).Model(m).Association("Stakeholders").Replace("Stakeholders", m.Stakeholders)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("StakeholderGroups").Replace("StakeholderGroups", m.StakeholderGroups)
if err != nil {
_ = ctx.Error(err)
return
}
if newAssessment {
metrics.AssessmentsInitiated.Inc()
}
Expand Down
35 changes: 33 additions & 2 deletions api/archetype.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,33 @@ func (h ArchetypeHandler) Create(ctx *gin.Context) {
}
m := r.Model()
m.CreateUser = h.CurrentUser(ctx)
result := h.DB(ctx).Create(m)
result := h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}

err = h.DB(ctx).Model(m).Association("Stakeholders").Replace("Stakeholders", m.Stakeholders)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("StakeholderGroups").Replace("StakeholderGroups", m.StakeholderGroups)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("CriteriaTags").Replace("CriteriaTags", m.CriteriaTags)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("Tags").Replace("Tags", m.Tags)
if err != nil {
_ = ctx.Error(err)
return
}

archetypes := []model.Archetype{}
db := h.preLoad(h.DB(ctx), "Tags", "CriteriaTags")
result = db.Find(&archetypes)
Expand Down Expand Up @@ -319,11 +340,21 @@ func (h ArchetypeHandler) AssessmentCreate(ctx *gin.Context) {
assessment.PrepareForArchetype(resolver, archetype, m)
newAssessment = true
}
result = h.DB(ctx).Create(m)
result = h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}
err = h.DB(ctx).Model(m).Association("Stakeholders").Replace("Stakeholders", m.Stakeholders)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("StakeholderGroups").Replace("StakeholderGroups", m.StakeholderGroups)
if err != nil {
_ = ctx.Error(err)
return
}
if newAssessment {
metrics.AssessmentsInitiated.Inc()
}
Expand Down
12 changes: 11 additions & 1 deletion api/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,21 @@ func (h StakeholderGroupHandler) Create(ctx *gin.Context) {
}
m := r.Model()
m.CreateUser = h.BaseHandler.CurrentUser(ctx)
result := h.DB(ctx).Create(m)
result := h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}
err = h.DB(ctx).Model(m).Association("Stakeholders").Replace(m.Stakeholders)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("MigrationWaves").Replace(m.MigrationWaves)
if err != nil {
_ = ctx.Error(err)
return
}
r.With(m)

h.Respond(ctx, http.StatusCreated, r)
Expand Down
2 changes: 1 addition & 1 deletion api/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (h IdentityHandler) AddRoutes(e *gin.Engine) {
routeGroup.GET(IdentitiesRoot+"/", h.setDecrypted, h.List)
routeGroup.POST(IdentitiesRoot, h.Create)
routeGroup.GET(IdentityRoot, h.setDecrypted, h.Get)
routeGroup.PUT(IdentityRoot, h.Update, Transaction)
routeGroup.PUT(IdentityRoot, Transaction, h.Update)
routeGroup.DELETE(IdentityRoot, h.Delete)
}

Expand Down
17 changes: 16 additions & 1 deletion api/migrationwave.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,26 @@ func (h MigrationWaveHandler) Create(ctx *gin.Context) {
}
m := r.Model()
m.CreateUser = h.CurrentUser(ctx)
result := h.DB(ctx).Create(m)
result := h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}
err = h.DB(ctx).Model(m).Association("Applications").Replace("Applications", m.Applications)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("Stakeholders").Replace("Stakeholders", m.Stakeholders)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("StakeholderGroups").Replace("StakeholderGroups", m.StakeholderGroups)
if err != nil {
_ = ctx.Error(err)
return
}
r.With(m)

h.Respond(ctx, http.StatusCreated, r)
Expand Down
22 changes: 21 additions & 1 deletion api/stakeholder.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,31 @@ func (h StakeholderHandler) Create(ctx *gin.Context) {
}
m := r.Model()
m.CreateUser = h.BaseHandler.CurrentUser(ctx)
result := h.DB(ctx).Create(m)
result := h.DB(ctx).Omit(clause.Associations).Create(m)
if result.Error != nil {
_ = ctx.Error(result.Error)
return
}
err = h.DB(ctx).Model(m).Association("Groups").Replace(m.Groups)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("Owns").Replace(m.Owns)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("Contributes").Replace(m.Contributes)
if err != nil {
_ = ctx.Error(err)
return
}
err = h.DB(ctx).Model(m).Association("MigrationWaves").Replace(m.MigrationWaves)
if err != nil {
_ = ctx.Error(err)
return
}
r.With(m)

h.Respond(ctx, http.StatusCreated, r)
Expand Down

0 comments on commit 9fca425

Please sign in to comment.