Work with Ent ORM schemas and generated code. Use when modifying ent schemas, debugging ent query issues, or dealing with Postgres type mappings.
75
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Guidance for working with Ent in the OpenMeter codebase.
openmeter/ent/schema/*.go (source of truth)openmeter/ent/db/ (DO NOT edit manually)After any schema change, regenerate with make generate before running tests.
text[])field.Strings(...) for Postgres array columns. Without an explicit schema type it creates jsonb, and with SchemaType(map[string]string{dialect.Postgres: "text[]"}) it changes DDL without changing the runtime encode/decode path for field.Strings.field.Other(..., pq.StringArray{}).SchemaType(map[string]string{dialect.Postgres: "text[]"}) for native Postgres text[] encode/decode with Ent methods (create/query/update). Import github.com/lib/pq in the schema file.entselectedparse extension (openmeter/ent/db/selectedparse.go) instead of hand-written scanners.db.Parse<Entity>FromSelectedValues(prefix, row.Value) for aliased joined columns.
db.ParseLedgerDimensionFromSelectedValues("dimension_", row.Value)deleted_at in the unique constraint (e.g., index.Fields("namespace", "key", "deleted_at").Unique()) — always filter with Where(<entity>db.DeletedAtIsNil()) in queries.char(26) schema type to match ULID IDs.entsql.OnDelete(entsql.Cascade) on the parent edge.NAMEDATALEN). Long Ent-generated table, index, and FK names can truncate and collide even when their full names differ. When a schema/entity/edge name is verbose, proactively shorten generated FK symbols with StorageKey(edge.Symbol("...")) and shorten index names with StorageKey("...") before generating migrations.entutils.JSONStringValueScanner — see openmeter/ent/schema/llmcostprice.go.field.String(...).NotEmpty() enforces Ent-side validation, but Atlas may still diff only SET NOT NULL for existing tables. If the database must reject empty strings too, add an explicit entsql.Checks(...) annotation in the schema or mixin alongside NotEmpty().UpdateNewValues() only updates fields that were set on the create mutation. If an upsert must clear a previously set nullable/optional column, explicitly chain the generated Update<Field>() method for that field after UpdateNewValues() (for example UpdateDescription() or UpdateDeletedAt()). This lets Ent use the excluded insert value, including NULL, instead of leaving the old value untouched. See billing adapter upserts such as openmeter/billing/adapter/stdinvoicelines.go.SetOrClear<Field> helpers: prefer these helpers for nullable/optional update fields when they have a straightforward signature. For awkward generated signatures such as double-pointer JSON fields, prefer the explicit pattern used for fields like normalized metadata: if value != nil { update = update.Set<Field>(value) } else { update = update.Clear<Field>() }. This avoids passing the address of a nil pointer, which can make Ent treat the field as set with a nil value and then panic or fail in generated validators.SetNillable<Field> for pointer GoTypes: when an optional field's GoType is already a pointer (e.g. field.String(...).GoType(&productcatalog.UnitConfig{}).ValueScanner(...)), Ent does not generate a SetNillable<Field> variant — Set<Field> itself takes the pointer. On create paths, guard with if value != nil { create = create.Set<Field>(value) } (see unit_config in openmeter/billing/charges/usagebased/adapter/charge.go and applied_unit_config in openmeter/billing/adapter/stdinvoicelines.go); leaving the field unset writes NULL on insert and leaves the existing value untouched on conflict-update.Depending on the change, the generators need to be re-run. For schema changes, edit files under openmeter/ent/schema/ and run the repo generation target:
# Regenerate all generated Go code, including Ent
make generateDuring local iteration, you can use the narrower Ent-only command when you intentionally want to avoid a full generation run:
# Regenerate Ent only after schema changes
go generate ./openmeter/ent/...5936703
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.