I’m trying to figure out how to do this, and have come up with something that may be the completely wrong approach.
Imagine we have a resource that represents a column
in a table. Each column has a number
so I can easily represent it; just sort :asc
in order, and draw from left-to-right.
Now, someone wants to change the order of the columns. I think there are two (fundamental) approach here: 1) I could read all the columns into memory, reorder them at the UI level, and then update the entire set. Maybe that’s the best option. But I started down the path of writing a update :set_column_number
that looks like this:
NOTE this is all basically pseudocode, as I haven’t got it working.
update :set_column_number do
argument :new_number, :integer
change Api.Column.Preparations.SetNumber
end
My thinking is that the preparation could reorder the necessary columns. This is where I’m heading with it:
defmodule Api.Column.Preparations.SetNumber do
def change(changeset, _, _) do
current_number = Ash.Changeset.get_attribute(changeset, :number)
new_number = Ash.Changeset.get_argument(changeset, :new_number)
# change the target column to it's new position
Ash.Changeset.change_attribute(changeset, :column, new_number)
# collect any other affected columns that we need to re-order
other_columns = Api.Column
|> Ash.Query.filter(number >= ^new_column and number != ^number)
|> Api.read!()
# re-order them (well, create a changeset for the lot of them anyhow)
all_changes = for column <- other_columns do
column
|> Ash.Changeset.for_update(:update, [number: number + 1])
end
# hand-wavy magic about combining the changesets and "it just works"
# hint: (it doesn't, I get back an list of changesets and... not sure what next)
all_changes ++ changeset
end
In theory it seems like it should work. Main questions:
- Is there a better way to do it (using Ash, versus in the UI layer)
- And if this isn’t a really bad approach, how to fix up the last little bit (after combining the changesets)?