Documentation
¶
Overview ¶
Package factory builds typed ORM drafts and persists them through the ordinary model lifecycle. It never resets data or substitutes raw inserts.
Index ¶
- Constants
- func CreateFor[M, D, P, PD any](ctx context.Context, writer database.Transactor, child *Factory[M, D], ...) (M, P, error)
- func CreateHas[M, D, C, CD any](ctx context.Context, writer database.Transactor, f *Factory[M, D], ...) (M, []C, error)
- func Pick[T any](f *Faker, items ...T) T
- type AfterCreate
- type Build
- type Factory
- func (f *Factory[M, D]) AfterCreating(hooks ...AfterCreate[M]) (*Factory[M, D], error)
- func (f *Factory[M, D]) Create(ctx context.Context, writer database.Transactor) (M, error)
- func (f *Factory[M, D]) CreateMany(ctx context.Context, writer database.Transactor, count int) ([]M, error)
- func (f *Factory[M, D]) CreateWith(ctx context.Context, writer database.Transactor, overrides ...State[D]) (M, error)
- func (f *Factory[M, D]) Draft(ctx context.Context) (D, error)
- func (f *Factory[M, D]) DraftWith(ctx context.Context, overrides ...State[D]) (D, error)
- func (f *Factory[M, D]) WithStates(states ...State[D]) (*Factory[M, D], error)
- type Faker
- func (f *Faker) Bool() bool
- func (f *Faker) Email() string
- func (f *Faker) FirstName() string
- func (f *Faker) Float() float64
- func (f *Faker) IntBetween(low, high int64) int64
- func (f *Faker) LastName() string
- func (f *Faker) Name() string
- func (f *Faker) Sentence() string
- func (f *Faker) TimeBetween(from, to time.Time) time.Time
- func (f *Faker) Word() string
- func (f *Faker) Words(count int) []string
- type Sequence
- type State
Constants ¶
const MaxCount = querycore.MaxPerModelWriteRows
const MaxHooks = 16
MaxHooks bounds a factory's after-create hooks.
const MaxStates = 64
Variables ¶
This section is empty.
Functions ¶
func CreateFor ¶
func CreateFor[M, D, P, PD any](ctx context.Context, writer database.Transactor, child *Factory[M, D], parent *Factory[P, PD], assign func(D, P) D) (M, P, error)
CreateFor creates one parent through its own factory, then one model that belongs to it. assign copies the parent's key into the child's draft, for example `func(d PostDraft, u User) PostDraft { return d.SetAuthorID(u.ID) }`. Both inserts use writer and their ordinary model lifecycle.
func CreateHas ¶
func CreateHas[M, D, C, CD any](ctx context.Context, writer database.Transactor, f *Factory[M, D], child *Factory[C, CD], count int, assign func(CD, M) CD) (M, []C, error)
CreateHas creates one model through f, then count children that belong to it through the child factory in one bounded CreateMany batch.
Types ¶
type AfterCreate ¶
AfterCreate runs after a model was inserted, inside the transaction that inserted it; writer is that transaction. It can create related records or return a reloaded model. A returned error or panic rolls back the insert, the hooks' own writes and, for CreateMany, the whole batch.
type Factory ¶
type Factory[M, D any] struct { // contains filtered or unexported fields }
Factory owns a sequence and immutable state callbacks. Derived states share their parent's sequence, preventing accidental reuse across variants. Each Define call has independent state. Callbacks must themselves support concurrent calls when the factory is shared; each invocation returns its own draft.
func Define ¶
func Define[M any, K comparable](table orm.Table[M, K], build Build[[]orm.Assignment[M]]) (*Factory[M, []orm.Assignment[M]], error)
Define builds an ORM factory from an explicit table and typed assignments. States, composition and after-create hooks share the ordinary factory contract. Example: factory.Define(Users.Table,func(ctx context.Context,n factory.Sequence)([]orm.Assignment[User],error){return []orm.Assignment[User]{orm.TextSet(Users.Name, "Ada")},nil}).
func (*Factory[M, D]) AfterCreating ¶
func (f *Factory[M, D]) AfterCreating(hooks ...AfterCreate[M]) (*Factory[M, D], error)
AfterCreating returns a derived factory that runs hooks, in order, after each Create and after every model of CreateMany. The factory is unchanged.
func (*Factory[M, D]) Create ¶
Create uses normal defaults/UUID preparation, field transformations, model observers, timestamps and the caller's actual transaction owner. With AfterCreating hooks, the insert and every hook share one transaction (a savepoint inside the caller's transaction), so a failing hook leaves no row.
func (*Factory[M, D]) CreateMany ¶
func (f *Factory[M, D]) CreateMany(ctx context.Context, writer database.Transactor, count int) ([]M, error)
CreateMany is atomic, bounded and ordered. Every input executes its normal model hooks through InsertEach, and AfterCreating hooks run in the same transaction (a savepoint inside the caller's transaction). A later failure, including a failing hook, rolls back the whole batch and its after-commit work; factories never switch to the hook-free bulk API.
func (*Factory[M, D]) CreateWith ¶
func (f *Factory[M, D]) CreateWith(ctx context.Context, writer database.Transactor, overrides ...State[D]) (M, error)
CreateWith creates one model with per-call attribute overrides, for example `func(_ context.Context, d UserDraft) (UserDraft, error) { return d.SetName("Ada"), nil }`. The overrides are not retained by the factory.
func (*Factory[M, D]) Draft ¶
Draft performs no database work. An attempted build consumes its sequence number even on failure; numbers are never reset or silently reused.
type Faker ¶
type Faker struct {
// contains filtered or unexported fields
}
Faker produces deterministic synthetic test values from a seed, so a failing test can be reproduced. It is safe for concurrent use; concurrent callers share one stream, so their interleaving decides which values each receives. Values are fictional and use reserved example domains; never production data.
func (*Faker) Email ¶
Email returns an address at the reserved example.test domain. Addresses from one Faker are unique because each carries a per-generator counter.
func (*Faker) IntBetween ¶
IntBetween returns an integer in the inclusive range [low, high].
func (*Faker) TimeBetween ¶
TimeBetween returns an instant in [from, to), truncated to microseconds so it round-trips through PostgreSQL timestamps.