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  }