I’ve created a module of CRUD operations, mostly one-liners, but I’m stuck at creating a general purpose update function.
Goals:
- Update the value of any key or keys in the row, independently of each other.
- Insert and or update the
:updated_at
key. - Only update the keys specified by the update functions arguments
My approach so far has been something along these lines (pseudo code):
......
defmodule Todo do
use Memento.Table,
attributes: [:id, :name, :priority, :updated_at],
type: :ordered_set,
autoincrement: true
.....
def update(id, changes = %{}) do
Memento.transaction do
case get_by_id(id) do
%Todo{} = todo ->
todo
|> adjust( changes)
|> Map.put!(:updated_at, NaiveDateTime.utc_now()
_ ->
{:error, :not_found}
end
end
defp adjust(%Todo{} = todo, changes) do
todo
|> Map.update!(changes))
|> Todo.write()
end
def get_by_id(id) do
Memento.transaction(fn -> Memento.Query.read(Todo, id) end)
end
Elixir school demonstrates updates with Mnesia.write/1
but this overwrites the whole row.
The other solutions I found are either over my head or in Erlang:
https://stackoverflow.com/questions/63048415/elixir-mnesia-what-is-the-most-concise-way-to-update-a-set-of-value-in-an-el
https://stackoverflow.com/questions/1820996/erlang-mnesia-updating-a-single-field-value-in-a-row