Renaming Multi operation names

Is there a way to rename multi operations before merging it? I mean without messing with struct internals of course.
Because I’m facing an issue similar to this:

def update_post_multi(post, title) do
   changeset = Changeset.change(post, title: title)
   Multi.new()
   |> Multi.update(:updated_post, post)
end

def update_posts(posts) do
    Enum.reduce(posts, Multi.new(), fn post, multi ->
        post
        |> update_post_multi()
        |> multi.prepend(multi)
    end)
    |> Repo.transaction()
end

I know that this wouldn’t work since names are expected to be unique, also that this can be solved by passing unique tuple keys such as {:updated_post, post.id} but my question is can I actually solve that at the update_posts level without changing the update_post_multi method?

1 Like

There’s no explicit API for that.

I’d suggest this for better composability:

def update_post(repo, post, title) do
  changeset = Changeset.change(post, title: title)
  repo.update(post, changeset)
end

def update_single_post(post, title) do
  Multi.new()
   |> Multi.run(:updated_post, fn repo, _ -> update_post(repo, post, title) end)
end

def update_multiple_post(posts) do
  Enum.reduce(posts, Multi.new(), fn {post, title}, multi ->
    Multi.run(multi, {:updated_post, post.id}, fn repo, _ -> update_post(repo, post, title) end)
  end)
  |> Repo.transaction()
end
3 Likes

Thank you for the suggestion! That’s probably what I’m going to end up doing, I asked just in case there is an alternative to having to refactor a considerable amount of logic located inside update_post_multi.

1 Like

You can add an argument the single update post function to give it an [extra] ID and just be done with it. Have that be the last argument and with a default value so it doesn’t break existing code.

1 Like

That could work too but if update_post_multi have more than one Multi operation it gets really weird passing a whole map/keyword list of names.