Run Transactions and Capturing Errors with Ecto.Multi

Learn how to run transactions with Ecto.Multi and examine errors.

The Ecto.Multi struct

The other way to use Repo.transaction is to pass in an Ecto.Multi struct rather than a function. The Ecto.Multi struct allows us to group our database operations into a data structure. When handed to the transaction function, the Multi’s operations run in order. If any of them fail, all of the others are rolled back.

Let’s take a look at an earlier example where we ran a transaction with an anonymous function.

Press + to interact
artist = %Artist{name: "Johnny Hodges"}
Repo.transaction(fn ->
Repo.insert!(artist)
Repo.insert!(Log.changeset_for_insert(artist))
end)

Here’s how we can rewrite it using Multi.

Press + to interact
alias Ecto.Multi
artist = %Artist{name: "Johnny Hodges"}
multi =
Multi.new\
|> Multi.insert(:artist, artist)\
|> Multi.insert(:log,Log.changeset_for_insert(artist))
Repo.transaction(multi)

There’s a lot here, so let’s walk through it.

A walkthrough

  1. We created a new Multi with the new function. The Ecto team recommends using this approach rather than trying to create the struct directly—don’t try to write something like multi = %Multi{}. The exact structure of Ecto.Multi is subject to future change. When we call new, it ensures that the struct will be properly initialized to us. If we create the ...

Create a free account to view this lesson.

By signing up, you agree to Educative's Terms of Service and Privacy Policy