Closed 2FO closed 2 years ago
Hi @2FO, it would be a mistake to compare mnesia
(and hence, memento
) to SQL databases because the design approaches are very different.
In :mnesia
, you'll first need to read the record, make changes to the fields and then write it back, all in the same transaction:
def update(id, %{} = changes) do
Memento.transaction(fn ->
case Memento.Query.read(Todo, id, lock: :write) do
%Todo{} = todo ->
todo
|> struct(changes)
|> Map.put(:updated_at, NaiveDateTime.utc_now())
|> Memento.Query.write()
|> then(&{:ok, &1})
nil ->
{:error, :not_found}
end
end)
end
I made a minor optimization here by using :write
lock on the read operation. The struct/2
method is useful when applying changes to structs, however, you probably want to use custom validation separately. You can modify this method a bit to make it generic and work with different records and validation systems.
As an example, you can also look at how Que
uses Memento underneath.
@sheharyarn Thank you very much for the solution, and tips. I'll definitely check out Que
and have read of the Mnesia
docs.
I x-posted this question on the elixir forum, so I'll add your solution to the thread.
I’ve created a module of CRUD operations, mostly one-liners, but I’m stuck at creating a general purpose update function. Goals:
My approach so far has been something along these lines (pseudo code):
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: