thojanssens1

thojanssens1

From `Repo.insert/2` to `Repo.transaction/2`

I have to convert the following code using Repo.insert/2

def create_question(attrs) do
  %Question{}
  |> Question.creation_changeset(attrs)
  |> Repo.insert()
end

to use a transaction:

def create_question(attrs) do
  question_changeset =
    Question.creation_changeset(%Question{}, attrs)

  Multi.new()
  |> Multi.insert(:question, question_changeset)
  |> Multi.run(:do_something, fn _repo, %{question: question} ->
    # do something
    {:ok, nil}
  end)
  |> Repo.transaction()
end

The problem is that now I have to change the code of my controller because the return value of Repo.transaction/2 is different than the return value of Repo.insert/2.

The controller’s action code is the following:

def create(conn, %{"question" => question_params}) do
  case Quiz.create_question(question_params) do
    {:ok, question} ->
      conn
      |> put_flash(:info, "Question created successfully.")
      |> redirect(to: Routes.admin_question_path(conn, :show, question))

    {:error, %Ecto.Changeset{} = changeset} ->
      render(conn, "new.html", changeset: changeset)
  end
end

I think it’s wrong to change controller’s code whether I use a transaction or not? I think that the controller always either needs a struct or a changeset to display the errors, just as Repo.insert/2 returns?

Any advice is welcome on how to refactor that properly, on where I have to change code.

Marked As Solved

idi527

idi527

:wave:

If you don’t need the full result including :do_something, then you can return the same tagged tuple as before:

def create_question(attrs) do
  question_changeset =
    Question.creation_changeset(%Question{}, attrs)

  Multi.new()
  |> Multi.insert(:question, question_changeset)
  |> Multi.run(:do_something, fn _repo, %{question: question} ->
    # do something
    {:ok, nil}
  end)
  |> Repo.transaction()
  |> case do
    {:ok, %{question: question}} -> {:ok, question}
    {:error, :question, %Ecto.Changeset{} = changeset, _changes} -> {:error, changeset}
  end
end

Also Liked

LostKobrakai

LostKobrakai

You want to change the behavior of the function, but not change the values returned? You could manually add an error (and action) to question_changeset if you really want to. Just be aware that you might encounter errors, which are not really related to the form itself and therefore don’t fit that option.

LostKobrakai

LostKobrakai

How about {:error, :upload_failed}. Changesets are very good in folding error messages for fields, which in your case might work out as well, but they don’t have means of holding error messages, which are not specific to a certain field in the form.

LostKobrakai

LostKobrakai

There’s two parts to that. The public api of the context function and whatever is calling it (the controller in your case). The API of your context should return whatever you feel is needed to describe what happened. The controllers job is then to convert the result into stuff on the rendered website, which informs the user. Error tuples is one potential result your context function could have. If a caller is supposed to handle an error you’d not want to use raise.

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

Other popular topics Top

senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement