Ash FrameworkAF
Ash Framework3mo ago
25 replies
dmc

Ash Update Many with Different Values

Hi there! I'm a bit new to Ash so apologies if I am missing something, but I couldn't find this use case in Discord or Elixir Forum.

Let's say I have a Todo List with many Items. The items are ordered 1..n and I have to maintain the order when any items are updated or deleted and the user can control the order.

For example,
%Item{id: "A", order: 1}
%Item{id: "B", order: 2}
%Item{id: "C", order: 3}

and the user deletes the item with id: "B", the result should be
%Item{id: "A", order: 1}
%Item{id: "C", order: 2}


1. Can I make the update part of it atomic and is it worth it?
2. How do folks typically handle auth in nested cases?

This works, but at what cost??!

defmodule Item do
  actions do
    defaults [:read, :destroy]

    update :update_order do
      accept [:order]
    end
  end
end

defmodule List do
  actions do
    update :destroy_item_and_update_item_orders do
      require_atomic? false

      argument :item, :map, allow_nil?: false, description: "The item to destroy"
      argument :items, {:array, :map}, allow_nil?: false

      change before_action(fn changeset, context ->
               Ash.Changeset.get_argument(changeset, :item)
               |> Ash.Changeset.for_destroy(:destroy)
               |> Ash.destroy!(authorize?: false)

               changeset
             end)

      change before_action(fn changeset, context ->
               destroyed_item = Ash.Changeset.get_argument(changeset, :item)

               updated_items =
                 Ash.Changeset.get_argument(changeset, :items)
                 |> Enum.reject(&(&1.id == destroyed_item.id))
                 |> Enum.sort_by(& &1.order)
                 |> Enum.with_index(1)
                 |> Enum.map(fn {item, index} -> %{item | order: index} end)

               Ash.Changeset.manage_relationship(changeset, :items, updated_items,
                 on_match: {:update, :update_order}
               )
             end)
    end
  end
end


Thanks in advance!
Was this page helpful?