In general, there is no "nice" way to swap unique indexed values in SQL.
Two known solutions are 1) deleting and reinserting the rows, or 2) updating the rows to another placholder value before updating both of them.
You could take a similar approach in Ecto like this:
Solution 1:
episode = Repo.get(Episode, id)
next_episode = Repo.get_by(Episode, position: episode.position + 1)
if next_episode, do: Repo.delete(next_episode)
episode
|> Episode.changeset(%{position: episode.position + 1})
|> Repo.update()
if next_episode do
Repo.insert(%Episode{next_episode | position: episode.position})
end
Solution 2:
(You'll need to choose some "impossible" value as a placeholder. For example, if position must be positive, you can use a negative number)
episode = Repo.get(Episode, id)
next_episode = Repo.get_by(Episode, position: episode.position + 1)
if next_episode do
next_episode
|> Episode.changeset(%{position: -1})
|> Repo.update()
end
episode
|> Episode.changeset(%{position: episode.position + 1})
|> Repo.update()
if next_episode do
next_episode
|> Episode.changeset(%{position: episode.position})
|> Repo.update()
end
The second solution might be preferable if you have any foreign key constraints referencing Episode
.