Skip to content

feat: add generate_rest? option to seed_generator#2591

Draft
robesris wants to merge 1 commit intoash-project:mainfrom
robesris:feat/seed-generator-generate-rest
Draft

feat: add generate_rest? option to seed_generator#2591
robesris wants to merge 1 commit intoash-project:mainfrom
robesris:feat/seed-generator-generate-rest

Conversation

@robesris
Copy link

@robesris robesris commented Feb 25, 2026

Contributor checklist

Leave anything that you believe does not apply unchecked.

  • I accept the AI Policy, or AI was not used in the creation of this PR.
  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

Problem

seed_generator in its tuple form {Resource, %{attrs}} generates random values for all writable, non-generated attributes, even those not listed in the attributes map. This makes it easy to accidentally introduce nondeterminism into test generators — any attribute not explicitly pinned will receive a random value, which can cause flaky tests that are difficult to trace back to the generator.

Solution

Adds a generate_rest? option to seed_generator/2. When false, only attributes explicitly listed in the attributes map (and overrides) receive generated values. Unlisted attributes receive their resource-level default or nil (if allow_nil?). Raises with a clear message if a required attribute (allow_nil?: false, no default) is not provided, catching missing generators early.

seed_generator(
  {MyApp.Document, %{name: StreamData.string(:alphanumeric)}},
  generate_rest?: false
)

Defaults to true to preserve existing behavior.

When `generate_rest?: false` is passed to `seed_generator/2`, only
attributes explicitly provided in the attributes map (and overrides)
receive generated values. Unlisted attributes use their resource-level
default or nil. Raises clearly if a required attribute is missing.

Defaults to `true` to preserve existing behavior.
)
merged = Map.merge(attributes, Map.new(opts[:overrides] || %{}))

if opts[:generate_rest?] == false do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd flip the conditional, and use if Keyword.get(opts, :generate_rest?, true) do to make the access default to true.

)
merged = Map.merge(attributes, Map.new(opts[:overrides] || %{}))

if opts[:generate_rest?] == false do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

default =
if action_type == :create, do: attribute.default, else: attribute.update_default

if !attribute.allow_nil? && is_nil(default) && !Map.has_key?(generators, attribute.name) do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bit more to check here. If the attribute is a create or update action, then we have to check if it's in allow_nil_input (overrides required attributes) or require_attributes (makes an input required that would not normally be required). Otherwise this looks great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants