goyave.dev/goyave/v5@v5.0.0-rc9.0.20240517145003-d3f977d0b9f3/database/factory.go (about) 1 package database 2 3 import ( 4 "gorm.io/gorm" 5 "goyave.dev/copier" 6 "goyave.dev/goyave/v5/util/errors" 7 ) 8 9 // Factory an object used to generate records or seed the database. 10 type Factory[T any] struct { 11 generator func() *T 12 override *T 13 BatchSize int 14 } 15 16 // NewFactory create a new Factory. 17 // The given generator function will be used to generate records. 18 func NewFactory[T any](generator func() *T) *Factory[T] { 19 return &Factory[T]{ 20 generator: generator, 21 override: nil, 22 BatchSize: 100, 23 } 24 } 25 26 // Override set an override model for generated records. 27 // Values present in the override model will replace the ones 28 // in the generated records. 29 // This function expects a struct pointer as parameter. 30 // Returns the same instance of `Factory` so this method can be chained. 31 func (f *Factory[T]) Override(override *T) *Factory[T] { 32 f.override = override 33 return f 34 } 35 36 // Generate a number of records using the given factory. 37 func (f *Factory[T]) Generate(count int) []*T { 38 if count <= 0 { 39 return []*T{} 40 } 41 42 slice := make([]*T, 0, count) 43 44 for i := 0; i < count; i++ { 45 record := f.generator() 46 if f.override != nil { 47 if err := copier.CopyWithOption(record, f.override, copier.Option{IgnoreEmpty: true, DeepCopy: true, CaseSensitive: true}); err != nil { 48 panic(errors.NewSkip(err, 3)) 49 } 50 } 51 slice = append(slice, record) 52 } 53 return slice 54 } 55 56 // Save generate a number of records using the given factory, 57 // insert them in the database and return the inserted records. 58 func (f *Factory[T]) Save(db *gorm.DB, count int) []*T { 59 records := f.Generate(count) 60 61 if err := db.CreateInBatches(records, f.BatchSize).Error; err != nil { 62 panic(errors.New(err)) 63 } 64 return records 65 }