This code used to work, being able to put custom messages inside messages
depending on the various clauses and send those messages back to the front end.
I updated Elixir. Now messages
is always {}
when it gets sent back to the frontend. What do I have to do to get this old code to append messages to messages
now? It'll append them and I'll inspect right after and they will be there. But then at the end, nothing is in there.
All my other code still works, it's just messages
is never returning anything to the front end anymore because it becomes empty by the end of the function. It's like the variable scope inside the iff isn't the same, and its a whole different variable or something.
defmodule Api.Controllers.PutProductIsVegan do
import Api.UserProduct
alias Api.UserProduct, as: UserProduct
import Ecto.Query
import Api.Repo
import Plug.Conn
def parse_elem("true"), do: true
def parse_elem("false"), do: false
def put_product_is_vegan(conn) do
messages = {}
db_user_product = %{}
product = Api.Product |> Api.Repo.get(conn.query_params["p_id"])
vegan_count = product.vegan_count
not_vegan_count = product.not_vegan_count
confirm = parse_elem(conn.body_params["confirm"])
report = parse_elem(conn.body_params["report"])
IO.inspect(confirm, label: "confirm")
IO.inspect(report, label: "report")
uid = conn.query_params["u_id"]
pid = conn.query_params["p_id"]
IO.inspect(uid, label: "confirm")
IO.inspect(pid, label: "report")
user_product = (from up in Api.UserProduct,
where: up.u_id == ^uid,
where: up.p_id == ^pid)
|> Api.Repo.one
IO.inspect(user_product)
if !user_product do
IO.puts("insert user product")
UserProduct.insert_user_product(conn, %{
p_id: String.to_integer(pid),
u_id: uid,
voted_not_vegan: report,
voted_vegan: confirm
})
end
user_product = (from up in Api.UserProduct,
where: up.u_id == ^uid,
where: up.p_id == ^pid)
|> Api.Repo.one
IO.inspect(user_product)
if !user_product.voted_not_vegan && report do
IO.puts("add 1 to product.not_vegan_count")
changeset = Api.Product.changeset(
product, %{:not_vegan_count => not_vegan_count + 1}
)
case Api.Repo.update(changeset) do
{:ok, product} ->
messages = Tuple.append(messages, "Product updated")
{:error, changeset} ->
messages = Tuple.append(messages, "Product not updated")
end
IO.puts("set up.voted_not_vegan to true")
changeset = Api.UserProduct.changeset(
user_product, %{:voted_not_vegan => true}
)
case Api.Repo.update(changeset) do
{:ok, product} ->
messages = Tuple.append(messages, "Product updated")
{:error, changeset} ->
messages = Tuple.append(messages, "Product not updated")
end
end
if !user_product.voted_vegan && confirm do
IO.puts("add 1 to product.vegan_count")
changeset = Api.Product.changeset(
product, %{:vegan_count => vegan_count + 1}
)
case Api.Repo.update(changeset) do
{:ok, product} ->
messages = Tuple.append(messages, "Product updated")
{:error, changeset} ->
messages = Tuple.append(messages, "Product not updated")
end
IO.puts("set up.voted_vegan to true")
IO.inspect (user_product)
changeset = Api.UserProduct.changeset(
user_product, %{:voted_vegan => true}
)
case Api.Repo.update(changeset) do
{:ok, product} ->
messages = Tuple.append(messages, "Product updated")
{:error, changeset} ->
messages = Tuple.append(messages, "Product not updated")
end
end
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Poison.encode!(%{
successs: "success",
errors: Tuple.to_list(messages)
}))
end
end
EDIT
From Adams answer I have done this, but the messages
is still blank at the end:
defmodule Api.Controllers.PutProductIsVegan do
import Api.UserProduct
alias Api.UserProduct, as: UserProduct
import Ecto.Query
import Api.Repo
import Plug.Conn
def parse_elem("true"), do: true
def parse_elem("false"), do: false
def put_product_is_vegan(conn) do
messages = {}
db_user_product = %{}
product = Api.Product |> Api.Repo.get(conn.query_params["p_id"])
vegan_count = product.vegan_count
not_vegan_count = product.not_vegan_count
confirm = parse_elem(conn.body_params["confirm"])
report = parse_elem(conn.body_params["report"])
IO.inspect(confirm, label: "confirm")
IO.inspect(report, label: "report")
uid = conn.query_params["u_id"]
pid = conn.query_params["p_id"]
IO.inspect(uid, label: "confirm")
IO.inspect(pid, label: "report")
user_product = (from up in Api.UserProduct,
where: up.u_id == ^uid,
where: up.p_id == ^pid)
|> Api.Repo.one
IO.inspect(user_product)
if !user_product do
IO.puts("insert user product")
UserProduct.insert_user_product(conn, %{
p_id: String.to_integer(pid),
u_id: uid,
voted_not_vegan: report,
voted_vegan: confirm
})
end
user_product = (from up in Api.UserProduct,
where: up.u_id == ^uid,
where: up.p_id == ^pid)
|> Api.Repo.one
IO.inspect(user_product)
if user_product.voted_not_vegan && report do
messages = Tuple.append(messages, "You have already reported this product")
end
if !user_product.voted_not_vegan && report do
IO.puts("add 1 to product.not_vegan_count")
changeset = Api.Product.changeset(
product, %{:not_vegan_count => not_vegan_count + 1}
)
messages =
case Api.Repo.update(changeset) do
{:ok, product} -> Tuple.append(messages, "Product updated")
{:error, changeset} -> Tuple.append(messages, "Product not updated")
end
IO.puts("set up.voted_not_vegan to true")
changeset = Api.UserProduct.changeset(
user_product, %{:voted_not_vegan => true}
)
messages =
case Api.Repo.update(changeset) do
{:ok, product} -> Tuple.append(messages, "Product updated")
{:error, changeset} -> Tuple.append(messages, "Product not updated")
end
end
if !user_product.voted_vegan && confirm do
IO.puts("add 1 to product.vegan_count")
changeset = Api.Product.changeset(
product, %{:vegan_count => vegan_count + 1}
)
messages =
case Api.Repo.update(changeset) do
{:ok, product} -> Tuple.append(messages, "Product updated")
{:error, changeset} -> Tuple.append(messages, "Product not updated")
end
IO.puts("set up.voted_vegan to true")
IO.inspect (user_product)
changeset = Api.UserProduct.changeset(
user_product, %{:voted_vegan => true}
)
messages =
case Api.Repo.update(changeset) do
{:ok, product} -> Tuple.append(messages, "Product updated")
{:error, changeset} -> Tuple.append(messages, "Product not updated")
end
end
IO.inspect(messages) # this is {}
conn
|> put_resp_content_type("application/json")
|> send_resp(200, Poison.encode!(%{
successs: "success",
errors: Tuple.to_list(messages)
}))
end
end
Your problem is that in statements like this:
case Api.Repo.update(changeset) do
{:ok, product} ->
messages = Tuple.append(messages, "Product updated")
{:error, changeset} ->
messages = Tuple.append(messages, "Product not updated")
end
Although you are assigning to messages
, that is scoped to inside the case statement. You're effectively appending to the tuple, assigning that to a new scoped variable that also happens to be called messages
, then discarding it. Then you're using the original declaration of messages = {}
when you do Tuple.to_list(messages)
.
You should be able to fix it by assigning the result of the case statement to messages
:
messages =
case Api.Repo.update(changeset) do
{:ok, product} -> Tuple.append(messages, "Product updated")
{:error, changeset} -> Tuple.append(messages, "Product not updated")
end
Unfortunately it looks like you need a lot of restructuring, because the code is using a mutable coding style in an immutable language. If you wanted to restructure, you could do something like this:
Define a function that accepts a list of messages, and conditionally adds a new message:
def add_message_if(messages, message, true), do: [message | messages]
def add_message_if(messages, _message, false), do: messages
Then you can call it in a chain like this:
messages =
[]
|> add_message_if("You have already reported this product", user_product.voted_not_vegan)
|> add_message_if("Product updated", !user_product.voted_not_vegan && updated?)
|> add_message_if("Product not updated", !user_product.voted_not_vegan && !updated?)
...
Then finally, Enum.reverse(messages)
, because we were prepending the messages.