Skip to content

Instantly share code, notes, and snippets.

@marka2g
Last active April 14, 2023 19:41
Show Gist options
  • Save marka2g/2276abe7992e8ee918720e69e6b5d947 to your computer and use it in GitHub Desktop.
Save marka2g/2276abe7992e8ee918720e69e6b5d947 to your computer and use it in GitHub Desktop.
Ecto.Multi BankAccount Example
deposit_query = from(BankAccount, where: [id: 2]) #deposit target bank account
withdraw_query = from(BankAccount, where: [id: 1]) #withdraw from bank account
deposit_update = [inc: [balance: 100]]
withdraw_update = [inc: [balance: -100]
alias Ecto.Multi
# iex> h Ecto.Multi # Multi.new() creates a one-time op that atomically groups transactions
# iex> h Ecto.Multi.update_all # def update_all(multi, name, queryable_or_fun, updates, opts \\ [])
Multi.new()
|> Multi.update_all(:deposit, deposit_query, deposit_update)
|> Multi.update_all(:withdraw, withdraw_query, withdraw_update)
##output
%Ecto.Multi{
names: #MapSet<[:deposit, :withdraw]>,
operations: [
withdraw: {:update_all,
#Ecto.Query<from a0 in MyApp.BankAccount, where: a0.id == 1>,
[inc: [balance: -100]], []},
deposit: {:update_all,
#Ecto.Query<from a0 in MyApp.BankAccount, where: a0.id == 2>,
[inc: [balance: 100]], []},}
]
}
#no logging yet because we havent ran the transaction yet
Multi.new()
|> Multi.update_all(:deposit, deposit_query, deposit_update)
|> Multi.update_all(:withdraw, withdraw_query, withdraw_update)
|> MyApp.Repo.transaction
##output
# [debug] Query OK db=0.2ms
# begin []
# [debug] QUERY OK source="bank_accounts" db=0.8ms
# UPDATE "bank_accounts" AS a0 SET "balance" = a0."balance" + $1 WHERE (a0."id" = 2) [50]
# [debug] QUERY OK source="bank_accounts" db=0.3ms
# UPDATE "bank_accounts" AS a0 SET "balance" = a0."balance" + $1 WHERE (a0."id" = 1) [-50]
# [debug] Query OK db=0.7ms
# commit []
# {:ok, %{deposit: {1, nil}, withdraw: {1, nil}}}
# https://hexdocs.pm/ecto/composable-transactions-with-multi.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment