fireproofsocks
Ecto.multi with insert and insert_all?
Is it possible to use an Ecto.Multi to do an insert and an insert_all where the insert_all needs the primary key resulting from the first insert? E.g. creating a parent record with numerous child records in one transaction.
The insert option can use a 3rd argument of changeset_or_struct_or_fun, but the insert_all function doesn’t allow for a function… so there doesn’t appear to be a good way to capture the primary key that gets generated.
I can wrap the steps inside of a Repo.transaction callback function like this:
Repo.transaction fn ->
with {:ok, parent} <- ParentContext.create(params),
{:ok, _children} <- create_children(parent, params)
do
else
{:error, e} -> Repo.rollback(e)
end
end
but I was curious if the multi supported it. Thanks!
Marked As Solved
axelson
Yeah you can using Multi.merge/2 (or Multi.run). It looks something like this:
Multi.new()
|> Multi.insert(:user, User.changeset(%User{}, params))
|> Multi.merge(fn %{user: user} ->
# That is the inserted user from the first part of the multi
Multi.new()
|> Multi.insert_all(:posts, build_insert_all_posts_changeset(user))
end)
|> Repo.transaction()
Also Liked
alxvallejo
What is this function??
LostKobrakai
You can’t directly. Repo.*_all are lower level APIs, which don’t support many schema or changeset features. You can map things from changeset to values for insert_all manually if you don’t need any of the not really supported parts.







