Ecto.Multi multiple inserts/updates with primary key of first insert

Continuing the discussion from How to make Ecto.Multi link multiple inserts where subsequent inserts require the primary key of the first operation?:

Expanding upon the example here, I’m taking it a step further with multiple inserts/updates using the primary key from the first insert and also an extra param passed to the function.

Users belong to many Teams which belong to many Cohorts. But Users are only in 1 Team per Cohort and there’s a joins table between the Cohorts and Users.

  1. User creates Team.
  2. Add Team_Id to Cohort_User joins table.
  3. Create Team_User joins table.
  4. Create Cohort_Team joins table.

The goal is to rollback all the transactions if one of them fails.

def create_team_and_associations(cohort_user, team_attrs \\ %{}) do
    Multi.new()
    |> Multi.insert(:team, Team.changeset(%Team{}, team_attrs) end)
    |> Multi.update(:cohort_user, fn %{team: %Team{id: team_id}} -> CohortUser.changeset(%CohortUser{team_id: team_id}) end)
    |> Multi.insert(:cohort_team, fn %{team: %Team{id: team_id}} -> CohortTeam.changeset(%CohortTeam{team_id: team_id, cohort_id: cohort_user.cohort_id}) end)
    |> Multi.insert(:team_user,   fn %{team: %Team{id: team_id}} -> TeamUser.changeset(%TeamUser{team_id: team_id, user_id: cohort_user.user_id}) end)
    |> Repo.transaction()
end

Am I doing this right?

I hope this example might help some others getting started working with Ecto.Multi!

This ended up working for me.

Multi.new()
    |> Multi.insert(:team, Team.changeset(%Team{}, team_attrs))
    |> Multi.update(:cohort_user,
        fn %{team: team} -> 
          CohortUser.changeset(cohort_user, %{"team_id" => team.id}) 
        end)
    |> Multi.insert(:cohort_team,
        fn %{team: team} ->
          CohortTeam.changeset(%CohortTeam{}, %{"team_id" => team.id, "cohort_id" => cohort_user.cohort_id})
        end)
    |> Multi.insert(:team_user,
      fn %{team: team} ->
        TeamUser.changeset(%TeamUser{}, %{"team_id" => team.id, "user_id" => cohort_user.user_id, "is_admin" => true})
      end)
    |> Repo.transaction()
2 Likes