I am trying to display the no_assoc_constraint message in a flash i.e when a website has blogs it errors
how do I access the message in the no_assoc_contraint in from the error
delete from context
def delete_website(%Website{} = website) do
website
|> Ecto.Changeset.change
|> Ecto.Changeset.no_assoc_constraint(:blogs, message: "error 1 blogs exist")
|> Ecto.Changeset.no_assoc_constraint(:posts, message: "error 2 posts exist")
|> Repo.delete
end
delete in controller
def delete(conn, %{"id" => id}, user) do
website = Repo.get!(user_websites(user), id)
|> Repo.preload(:user)
case Websites.delete_website(website) do
{:ok, _website} ->
conn
|> put_flash(:info, "Website deleted successfully.")
|> redirect(to: Routes.website_path(conn, :index))
{:error, %Ecto.Changeset{} = changeset} ->
conn
|> put_flash(:error, "Website delete issues: existing blogs or posts")
|> redirect(to: Routes.website_path(conn, :index))
end
end
Ideally I want to put the message from no_assoc_constraint in the flash i.e. Website delete issues: existing blogs or posts becomes error 1 blogs exist
Hi,
You can pattern match on the error and use it in the flash:
case Websites.delete_website(website) do
{:ok, _website} ->
conn
|> put_flash(:info, "Website deleted successfully.")
|> redirect(to: Routes.website_path(conn, :index))
{:error, %{ errors: errors } = changeset} ->
msg = handle_error(errors)
conn
|> put_flash(:error, msg)
|> redirect(to: Routes.website_path(conn, :index))
end
You can then match to the :key
of the error you are looking for:
defp handle_error({:key, { messge, _ }}), do: message
Remember you will need a catch all.
2 Likes
hello and thank-you @andrewb
I am not sure what you mean by the catchall
I add this
def delete(conn, %{"id" => id}, user) do
website = Repo.get!(user_websites(user), id)
|> Repo.preload(:user)
case Websites.delete_website(website) do
{:ok, _website} ->
conn
|> put_flash(:info, "Website deleted successfully.")
|> redirect(to: Routes.website_path(conn, :index))
{:error, %{ errors: errors } = changeset} ->
msg = handle_error(errors)
conn
|> put_flash(:error, msg)
|> redirect(to: Routes.website_path(conn, :index))
end
end
defp handle_error({:key, { message, _ }}), do: message
and get
no function clause matching in WebsiteController.handle_error/1
Called with 1 arguments
- [blogs: {“blogs exist”, [constraint: :no_assoc, constraint_name: “blogs_blogs_website_id_fkey”]}]
Attempted function clauses (showing 1 out of 1)
defp handle_error( {:key, {message, _}} )
Hi,
in the handle_error
you need to replace the :key
with the :key
for the error message you want to extract. The reference to catch all is that you need to handle any calls that don’t match on keys.
defp handle_error({PUT_YOUR_KEY_HERE, { message, _ }}), do: message
Then have have something like:
defp handle_error({all_errors, { _, _ }}), do: "Something went wrong!"
If you are not sure what the error :key
is you can IO.inspect(changeset)
and then cause the error.
Hope this helps.
Andrew
PS: I am doing this from memory … post again if you can’t work it out
thanks, yes, it very much helps
IO.inspect is giving me this
#Ecto.Changeset<
action: :delete,
changes: %{},
errors: [
blogs: {"blogs exist",
[constraint: :no_assoc, constraint_name: "blogs_blogs_website_id_fkey"]}
],
data: #Websites.Website<>,
valid?: false
now I need to work out how to pattern match on the map
thanks
had to add [ ] to pattern match
defp handle_error([{:blogs, {message, _}}]), do: message
now my flash says “blogs exist”
thanks @andrewb