More complex changes done atomically?

I have an update action that interpolates some string attributes with an accepted id that’s an integer:

    update :open do
      require_atomic? false
      atomic_upgrade? false
      accept [:*]

      change fn changeset, _ ->
        string_attribute_a = "A.#{changeset.attributes.some_integer_id}"
        string_attribute_b= "B.#{changeset.attributes.some_integer_id}"
        change_attributes(changeset, %{string_attribute_a: string_attribute_a , string_attribute_b: string_attribute_b})
      end
    end

This works but I failed to do it atomically. Is this something that’s not possible or am I missing something? I’m wondering @zachdaniel how would you do this better? :cowboy_hat_face:

Something like this would do what you want:

change atomic_update(:string_attribute_a, expr("A." <> atomic_ref(:some_integer_id))
change atomic_update(:string_attribute_b, expr("B." <> atomic_ref(:some_integer_id))

In general, though, you can often get more flexibility by extracting to a module change

defmodule MyApp.Changes.SetValues do
  use Ash.Resource.Change

  def atomic(changeset, ....) do
     {:atomic, %{
        string_attribute_a: expr(...),
        string_attribute_b: expr(...),
     }}
  end
end
2 Likes