Search code examples
postgresqlelixirecto

Within transaction: Use inserted id for reference to next insertion


I want to create a wallet for a user, when the user itself is being created. Ideally i want this to happen within a transaction, as one may not exist without the other.

I want something like this, in Ecto paradigm.

BEGIN;
  INSERT INTO albums [...];
  INSERT INTO album_images (lastval(), image_id) [...];
COMMIT;

Taken from https://github.com/elixir-ecto/ecto/issues/2154.

How would achieve such?


Solution

  • Consider using Multi and at the end you would put all the things processed in the Multi to Repo.transaction().

    Ecto.Multi will help you to organize this flow, because Multi.run accepts Multi structure that contains result of previous computation - that's why you can safely use it, because if first operation fails, the second one will be rejected by the transaction as well.

    The best way to write it is to put the business operations to separate functions, where the second one accept Multi with the name of the result of previous operation.

    Multi.new
    |> Multi.insert(:albums, insert_albums(arguments))
    |> Multi.run(:album_images, AlbumImage, :insert, [])
    |> Repo.transaction()
    

    where AlbumImage.insert might look like:

    defmodule AlbumImage do
      def insert(%{albums: albums}) do
        # code
      end
    end