ckhrysze
Exceptions within an ecto transaction
I’ve read in several places that try/rescue are to be generally avoided. However, I see no way around it in the following scenario (unless I’m just really missing something or discovered a bug, which I’m kinda hoping for…).
c is an invalid changeset
iex(4)> Repo.insert(c, [])
{:error, ...}
iex(5)> Repo.transaction(fn -> Repo.insert(c, []) end)
{:ok,
{:error,
...}}
iex(6)> Repo.transaction(fn -> {:ok, _} = Repo.insert(c, []) end)
** (MatchError) no match of right hand side value: {:error, ...}
Ideally there will be additional things in the transaction…but they are based on the inserted records value…I don’t want to wrap everything in a transaction with a try/rescue as well, but I’m not sure how to avoid it.
Also, I’ve glanced at, but don’t quite understand, ecto multi; though I’m not sure that helps if the second db action relies on data from the first.
Marked As Solved
benwilson512
It all just depends on what you’re trying to do. Because I’m not entirely sure what you’re trying to do, here are a few patterns you may find useful.
Try to insert inside a transaction, if it fails, do something else, but let the transaction succeed
Repo.transaction(fn ->
case Repo.insert(changeset) do
{:ok, record} -> handle_success(record)
_ -> do_something_else()
end
end)
Try to insert something, if it succeeds insert something else, and rollback everything if there’s a failure:
Repo.transaction(fn ->
with {:ok, record} <- Repo.insert(foo),
{:ok, other_record} <- Repo.insert(bar) do
{record, other_record}
else
val -> Repo.rollback(val)
end
end)
|> case do
{:ok, {foo, bar}} ->
IO.puts "Both foo and bar were created because the transaction succeedd"
{:error, error} ->
IO.puts "Neither foo nor bar were created because the transaction failed with error: #{inspect error}"
end
Also Liked
wojtekmach
Also, if you want to use Multi, Ecto.Multi.merge can be used to access data from previous operations.
EDIT: actually, using Ecto.Multi.run might be easier too.
ckhrysze
Thank you! I had tried to solve it with ‘with’, but I must have made another mistake in the process. Also, thank you @wojtekmach, I’ll look into multi.merge.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








