Key constraint pretiffy error

Hi everyone,

So i want to change the exception of constraint that I have for my categories to post to receive a put_flash(:danger, "This category belongs to a post, change the category on the post then you can delete this category ")
when I press the delete button for a category that is associated to a post?
How can i do that?

Thanks in advance

I think this a good use case for Ecto.Changeset.no_assoc_constraint.

You can learn more about it in the docs.

1 Like

In fact if category is a parent of posts, I think it’s better to say:
Category has many posts (or one post) and a post belongs to a category.

So my flash message would be something like:

“You cannot delete a category that contains posts. Make sure to delete all those posts or update their category if you still want to delete it.”

2 Likes

Thanks i will look over it tomorrow.

By the way where can i use Ecto.Changeset.no_assoc_constraint do i apply it on the category changeset direcly or create a new changeset for delete category?

Thanks.

Exactly that is the right way.

@doc false
  def delete_changeset(category) do
    category
    |> change
    |> no_assoc_constraint(:posts, message: "custom message")
  end

Also the docs don’t say explicitly how to catch the error in your controller.

So the easiest way to do it in your delete action will be something like this:

def delete(conn, %{"id" => id}) do
   category = Blog.get_category!(id)

    conn =
      case Blog.delete_category(category) do
        {:ok, _category} ->
          put_flash(conn, :info, "Category successfuly deleted.")

        {:error, changeset} ->
          put_flash(conn, :error, "You cannot delete this category....")
      end

    redirect(conn, to: Routes.category_path(conn, :index))
  end

Blog.delete_category is where you call the delete_changeset before piping to Repo.delete.

But if you want to use the default error message of Ecto you can check it in the changeset by matching it with %{errors: errors}. Then errors is keyword list where you can search the key :posts. Anyway just inspect it to know how to get what you want.

2 Likes

Thanks @Kurisu