From 0d49b61029be7baacef7682d840a13c939cbe2ef Mon Sep 17 00:00:00 2001 From: Rebecca Le <543859+sevenseacat@users.noreply.github.com> Date: Thu, 9 Jan 2025 20:06:12 +0800 Subject: [PATCH] fix: Fix issues in `Ash.Generator.generate_many/2` (#1703) * docs(`Ash.Generator`): Fix example code blocks to render // correctly * fix(`Ash.Generator`): Don't error if no `after_action` is provided to `generate_many` * fix(`Ash.Generator`): Reuse the changeset actor when calling `bulk_create` * chore(`Ash.Generator`): Read and send notifications created when generating many records This prevents warnings in tests when using `generate_many` - `[warning] Missed notifications in action ` * chore(`Ash.Generator`): Raise an error if the `bulk_create` command in `generate_many` wasn't a complete success A partial success would mean less records were inserted than were requested, definitely leading to buggy/flaky tests --- lib/ash/generator/generator.ex | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/ash/generator/generator.ex b/lib/ash/generator/generator.ex index d612eeb89..2ee639250 100644 --- a/lib/ash/generator/generator.ex +++ b/lib/ash/generator/generator.ex @@ -12,7 +12,7 @@ defmodule Ash.Generator do use Ash.Generator # using `seed_generator`, bypasses the action and saves directly to the data layer - def blog_post(opts \\ []) do + def blog_post(opts \\\\ []) do seed_generator( %MyApp.Blog.Post{ name: sequence(:title, &"My Blog Post \#{&1}") @@ -23,7 +23,7 @@ defmodule Ash.Generator do end # using `changeset_generator`, calls the action when passed to `generate` - def blog_post_comment(opts \\ []) do + def blog_post_comment(opts \\\\ []) do blog_post_id = opts[:blog_post_id] || once(:default_blog_post_id, fn -> generate(blog_post()).id end) changeset_generator( @@ -505,12 +505,27 @@ defmodule Ash.Generator do fn _changeset, record -> {:ok, after_action.(record)} end + else + # Do nothing + fn _changeset, record -> {:ok, record} end end - Ash.bulk_create!(Enum.map(batch, & &1.params), first.resource, first.action, - after_action: after_action, - return_records?: true - ).records || [] + result = + Ash.bulk_create!(Enum.map(batch, & &1.params), first.resource, first.action.name, + after_action: after_action, + return_records?: true, + return_errors?: true, + return_notifications?: true, + actor: first.context[:private][:actor] + ) + + if result.status != :success do + raise Ash.Error.to_error_class(result.errors) + end + + Ash.Notifier.notify(result.notifications) + + result.records || [] batch -> Enum.map(batch, fn record -> @@ -641,7 +656,7 @@ defmodule Ash.Generator do Generate input meant to be passed into `Ash.Seed.seed!/2`. A map of custom `StreamData` generators can be provided to add to or overwrite the generated input, - for example: `Ash.Generator.for_seed(Post, %{text: StreamData.constant("Post")})` + for example: `Ash.Generator.seed_input(Post, %{text: StreamData.constant("Post")})` """ @spec seed_input(Ash.Resource.t(), map()) :: StreamData.t(map()) def seed_input(resource, generators \\ %{}) do