Using captured function inside Ecto.Multi

Hi I have these ginormous function that contain many multi subroutine
Is it possible to tidy these anonymous function with capture

note evt is variable from outside scope

From something like this

    |> Multi.insert(
      :accumulated_balance,
      fn %{
           balance: %Balance{} = balance
         } ->
        %AccumulatedBalance{
          user_id: evt.user_id,
          product_id: evt.product_id,
          type: :lock,
          lock: evt.amount,
          release: Decimal.new(0),
          balance: updated_tiered_vault_balance.balance,
          balance_datetime: evt.locked_at
        }
      end
    )

to

Multi.insert(
      :tiered_vault_accumulated_balance,
      (&build_accumulated_balance/1)
)

Hi,

Unfortunately, that will not work, since evt is out of scope.
If you want to make use of Ecto.Multi, I think the best way to achieve that is to make use of Multi.put/3 and add the evt inside the multi.

Be aware that put/3 is being run before the transaction starts… If you need your data to be fetched inside of the transaction use Multi.run/3

So it could look something like this:

Multi.new()
|> Multi.put(:evt, my_event_data)
|> Multi.run(:balance, &fetch_balance/2)
|> Multi.insert(:tiered_vault_accumulated_balance, &build_accumulated_balance/1)
|> YourApp.Repo.transaction()

And your build_accumulated_balance/1 function could look something like:

def build_accumulated_balance(%{evt: event, balance: balance}) do
  %AccumulatedBalance{
    user_id: evt.user_id,
    product_id: evt.product_id,
    type: :lock,
    lock: evt.amount,
    release: Decimal.new(0),
    balance: updated_tiered_vault_balance.balance,
    balance_datetime: evt.locked_at
   }
end
2 Likes