Maybe You can test like this
iex> Ecto.UUID.cast "a863228-727c-4cf3-93f5-9b2f79df1288"
:error
iex> Ecto.UUID.cast Ecto.UUID.bingenerate()
{:ok, "767f998a-424b-4270-beff-742b93f636fc"}
Maybe You can test like this
iex> Ecto.UUID.cast "a863228-727c-4cf3-93f5-9b2f79df1288"
:error
iex> Ecto.UUID.cast Ecto.UUID.bingenerate()
{:ok, "767f998a-424b-4270-beff-742b93f636fc"}
It also depends on the properties you want your program to have. In this specific case I would prefer to return an error to the client saying that the UUID specified is invalid.
To add to @Ankhers’s advice, @shahryarjb you can add a plug which would transform this particular ecto error into an http response which is more appropriate for your use case.
defimpl Plug.Exception, for: Ecto.ChangeError do
def status(_exception), do: 400
end
You could replace your case with with.
with {:ok, _} <- Ecto.UUID.cast(cms_post_category_id),
{:ok, _post} <- PostQuery.insert_post(allreq)
do
...
end
Please see my suggestion code in my Phoenix Controller :
def create_cms_post(conn, %{"title" => _title, "status" => _status, "post_type" => _post_type, "download_ext_link" => _download_ext_link, "price" => _price, "pic_x1_link" => _pic_x1_link, "pic_x2_link" => _pic_x2_link, "pic_x3_link" => _pic_x3_link, "group_acl" => _group_acl, "description" => _description, "changelog" => _changelog, "changelog_category" => _changelog_category, "plugin" => _plugin, "plugin_category" => _plugin_category, "discourse" => _discourse, "discourse_link" => _discourse_link, "screen_shot" => _screen_shot, "screen_shot_category" => _screen_shot_category, "learn" => _learn, "learn_category" => _learn_category, "seo_tag" => _seo_tag, "seo_alias_link" => _seo_alias_link, "seo_words" => _seo_words, "seo_description" => _seo_description, "seo_language" => _seo_language, "seo_language_link" => _seo_language_link, "cms_post_category_id" => cms_post_category_id} = allreq) do
create_post(conn, allreq, Ecto.UUID.cast(cms_post_category_id))
end
defp create_post(conn, _allreq, :error) do
conn
|> put_status(400)
|> json(%{error_code: "400"})
end
defp create_post(conn, allreq, {:ok, _}) do
create_cms_posts = case PostQuery.insert_post(allreq) do
{:ok, _post} ->
conn
|> put_status(200)
|> json(%{message: "The post has been created."})
{:error, _changeset} ->
conn
|> put_status(403)
|> json(%{error_code: "403"})
end
create_cms_posts
end
Does anyone have a suggestion whether my code is invalid or valid?
It cannot work because Ecto.UUID.cast returns {:ok, _uuid}
UPDATE: Sorry, I didn’t read well
It seems to be ok, does this work?
I tested this several times and I didn’t have any problem. I think it works
Thank all of you whom helped me.
In Ecto3 when you specify in your model the primary key you can use Ecto.UUID instead of :binary_id so that the Ecto casting works correctly:
@primary_key {:id, Ecto.UUID, autogenerate: true}
schema "post" do
...
end
This way you should get the regular Ecto validations before going to the DB which looks like is what you want: {"id":"is invalid"}
From the ecto documentation:
… (typically
:id
or:binary_id
, but can be any type)
Thank you for this! So simple! It also works with belongs_to
:
belongs_to :post, Post, type: Ecto.UUID
Thanks!