Checking if records exist with Memento

I am using memento to wrap Mnesia functionality into my application.

I want to check if a record with a certain id exists and if not perform certain actions.

Documentation says read should return nil when record doesn’t exist. Howerver, the Memento.transation wrapper aborts with a :not_exists exception therefore my application cannot proceed.

Here’s how my function looks like:

def find_conversation(user_id) do
    Memento.transaction! fn ->
      user_id
      |> read
      |> to_conversation
    end
end

defp to_conversation(nil), do: nil
  defp to_conversation(%@store{} = conversation) do
    struct(Conversation, Map.from_struct(conversation))
  end

I cannot test it now, but I think you need to call to_conversation/1 outside the Memento transaction.

This is how I do in my app…

To get a resource:

def get_todo!(uid) do
    _read_transaction(uid)
  end

To read it from Mnesia:

defp _read_transaction(uid) do
    result = Memento.transaction fn -> Memento.Query.read(Todo, uid) end
    _parse_fetch_result(result)
end

To parse the result of reading it from Mnesia:

defp _parse_fetch_result(result) do
    case result do
      {:ok, nil} ->
        []
      {:ok, []} ->
        []
      {:ok, todo} ->
        todo
      {:error, error} ->
        Logger.error("_parse_resul/1: #{error}")
        Todo.new_changeset()
    end
  end

To note that the returned values foreach case are specific to my app.

Also bear in my mind that is app serves as a Learning path for me to know more about Mnesia and Elixir, thus I may also not doing it in the best way :wink:

1 Like

Thanks for your feedback. I followed your advise, no joy. This is how I did it but result is same

def find_conversation(user_id) do
    results = Memento.transaction! fn -> read(user_id) end
    results
    |> to_conversation
  end