Classic Elixir Bug

Data in Elixir is immutable. This can lead to some subtle bugs.

Here is the example Ecto.Multi sample

defmodule PasswordManager do
  alias Ecto.Multi

  def reset(account, params) do
    Multi.new()
    |> Multi.update(:account, Account.password_reset_changeset(account, params))
    |> Multi.insert(:log, Log.password_reset_changeset(account, params))
    |> Multi.delete_all(:sessions, Ecto.assoc(account, :sessions))
  end
end

This could be rewritten as

defmodule PasswordManager do
  alias Ecto.Multi

  def reset(account, params) do
    multi = Multi.new()
    multi = Multi.update(multi, :account, Account.password_reset_changeset(account, params))
    multi = Multi.insert(multi, :log, Log.password_reset_changeset(account, params))
    multi = Multi.delete_all(:sessions, Ecto.assoc(account, :sessions))
  end
end

Forget to capture the multi at any step and you will lose the specific change from the batch.

This is insidious when moving from the first to the second to add a calculated value or when the function you are adapting only uses one multi

Leave a comment