test "stores the actor that updated the record" do
actor = generate(user(role: :admin))
artist = generate(artist(name: "First Name"))
refute artist.updated_by_id == actor.id
artist = Music.update_artist!(artist, %{name: "Second Name"}, actor: actor)
assert artist.updated_by_id == actor.id
end
Looks very reasonable, but will currently fail with
For safety, we prevent any changes after that point because they will bypass validations or other action logic.. To proceed anyway,
you can use force_change_attribute/3. However, you should prefer a pattern like the below, which makes
any custom changes before calling the action.
Sorry, I’m not following the problem here. Those tests about recording who updated a record shouldn’t fail - they don’t fail in the app at the end of the testing chapter. If you’re seeing failures, can you share the full error with stacktrace?
And what exactly are you looking to update the generators to do?
Thank you for coming back to me. And apologies for potentially unnecessary thread.
I have figured the difference. My lib/tunez/music/changes/update_previous_names.ex looks like:
defmodule Tunez.Music.Changes.UpdatePreviousNames do
use Ash.Resource.Change
@impl true
def change(changeset, _opts, _context) do
Ash.Changeset.before_action(changeset, fn changeset ->
new_name = Ash.Changeset.get_attribute(changeset, :name)
previous_name = Ash.Changeset.get_data(changeset, :name)
previous_names = Ash.Changeset.get_data(changeset, :previous_names)
names =
[previous_name | previous_names]
|> Enum.uniq()
|> Enum.reject(fn name -> name == new_name end)
Ash.Changeset.change_attribute(changeset, :previous_names, names)
end)
end
end
While the version from the repo misses being wrapped in Ash.Changeset.before_action/2. Which was introduced on the page 57 (B6).
defmodule Tunez.Music.Changes.UpdatePreviousNames do
use Ash.Resource.Change
@impl true
def change(changeset, _opts, _context) do
new_name = Ash.Changeset.get_attribute(changeset, :name)
previous_name = Ash.Changeset.get_data(changeset, :name)
previous_names = Ash.Changeset.get_data(changeset, :previous_names)
names =
[previous_name | previous_names]
|> Enum.uniq()
|> Enum.reject(fn name -> name == new_name end)
Ash.Changeset.change_attribute(changeset, :previous_names, names)
end
end
Would that be an expected behavior then? I am pretty new to Ash, but using before_action/2 seemed as a good idea
The full error message:
19:30:59.110 [warning] Changeset has already been validated for action :update.
For safety, we prevent any changes after that point because they will bypass validations or other action logic.. To proceed anyway,
you can use `force_change_attribute/3`. However, you should prefer a pattern like the below, which makes
any custom changes *before* calling the action.
Resource
|> Ash.Changeset.new()
|> Ash.Changeset.change_attribute(...)
|> Ash.Changeset.for_create(...)
(elixir 1.18.3) lib/process.ex:896: Process.info/2
(ash 3.5.21) lib/ash/changeset/changeset.ex:6189: Ash.Changeset.change_attribute/3
(ash 3.5.21) lib/ash/changeset/changeset.ex:4522: anonymous fn/2 in Ash.Changeset.run_before_actions/1
(elixir 1.18.3) lib/enum.ex:4968: Enumerable.List.reduce/3
(elixir 1.18.3) lib/enum.ex:2600: Enum.reduce_while/3
(ash 3.5.21) lib/ash/changeset/changeset.ex:4497: Ash.Changeset.run_before_actions/1
(ash 3.5.21) lib/ash/changeset/changeset.ex:4636: Ash.Changeset.run_around_actions/2
(ash 3.5.21) lib/ash/changeset/changeset.ex:4189: anonymous fn/3 in Ash.Changeset.with_hooks/3
(ecto_sql 3.12.1) lib/ecto/adapters/sql.ex:1400: anonymous fn/3 in Ecto.Adapters.SQL.checkout_or_transaction/4
(db_connection 2.7.0) lib/db_connection.ex:1756: DBConnection.run_transaction/4
(ash 3.5.21) lib/ash/changeset/changeset.ex:4187: anonymous fn/3 in Ash.Changeset.with_hooks/3
(ash 3.5.21) lib/ash/changeset/changeset.ex:4331: anonymous fn/2 in Ash.Changeset.transaction_hooks/2
(ash 3.5.21) lib/ash/changeset/changeset.ex:4174: Ash.Changeset.with_hooks/3
(ash 3.5.21) lib/ash/actions/update/update.ex:435: Ash.Actions.Update.commit/3
(ash 3.5.21) lib/ash/actions/update/update.ex:308: Ash.Actions.Update.do_run/4
(ash 3.5.21) lib/ash/actions/update/update.ex:252: Ash.Actions.Update.run/4
(ash 3.5.21) lib/ash.ex:3629: Ash.update/3
(ash 3.5.21) lib/ash.ex:3547: Ash.update!/3
test/tunez/music/artist_test.exs:117: Tunez.Music.ArtistTest."test Tunez.Music.update_artist/2-3 collects old names when the artist name changes"/1
(ex_unit 1.18.3) lib/ex_unit/runner.ex:511: ExUnit.Runner.exec_test/2