Hello!
I’m trying to validate my entries using with
, but it is not clearly for me how to use it properly:
with {formatted_price, _} <- Float.parse price,
{:ok, formatted_sale_time} = Ecto.DateTime.cast(sale_time)
do
send_resp(conn, 201, "Cool!")
else #How do I send a response back for each error?
:error -> send_resp(conn, 400, "Price is invalid!")
:error -> send_resp(conn, 400, "Sale time is invalid!")
end
Thanks in advance!!
1 Like
You have to match on something more than just :error atom
3 Likes
Like @andre1sk said, you need to match on different clauses, if you have the same :error
clause twice it will match the first one. Here is a slightly modified version which works:
with {formatted_price, ""} <- Float.parse price,
{:ok, formatted_sale_time} = Ecto.DateTime.cast(sale_time)
do
send_resp(conn, 201, "Cool!")
else
{_, str} when is_binary(str) and byte_size(str) > 0 -> send_resp(conn, 400, "Price is invalid!")
:error -> send_resp(conn, 400, "Sale time is invalid!")
end
3 Likes
Thanks guys for the explanation !! I didn’t worked, but I’ve moved the validation trough the changeset model, like this:
sale = Momsfood.Sale.changeset(%Momsfood.Sale{}, conn.params)
if sale.valid? do
Momsfood.Repo.insert(sale)
send_resp(conn, 201, "")
else
send_resp(conn, 400, sale.errors)
end
But now I’m having trouble to send the errors back to the client
send_resp(conn, 400, sale.errors)
** (ArgumentError) argument error
stacktrace:
:erlang.iolist_to_binary([sale_time: "is invalid"])
How to parse the errors properly to send it back?
Thanks guys!!
Change that to send_resp(conn, 400, inspect(sale.errors))
send_resp
accepts an iolist
as the third argument. inspect
changes your errors object into a string so that should work.
Yay! It’s working now!
I was trying to encode into JSON using Poison, but I’m struggling with this error:
** (Poison.EncodeError) unable to encode value: {:sale_time, "is invalid"}
Here is what I was trying to do:
send_resp(conn, 400, Poison.encode!(sale.errors, []))
I was reading some issues related to that problem, but I didn’t manage to find a properly way solve that, even adding the @derive directive to my model:
@derive {Poison.Encoder, only: [:price, :sale_time]}
schema "sales" do
field :price, :float
field :sale_time, Ecto.DateTime
timestamps
end
Hey guys, I’ve manage to make it works!!
if sale.valid? do
Momsfood.Repo.insert(sale)
send_resp(conn, 201, "")
else
errors = Enum.into(sale.errors, %{})
send_resp(conn, 400, Poison.encode!(errors))
end
I’ve ended up converting my errors to a map, which is the correctly format expected by Poison.
Thanks for helping guys!!
1 Like