sharkmyster

sharkmyster

How to handle constraint error when deleting record from adjacency list?

I’m using an adjacency list to store a hierarchy of categories. There can be many root categories each with many children/descendants.

defmodule WordSolverDal.Categories.Category do
  use Ecto.Schema
  import Ecto.Changeset

  use Arbor.Tree,
    foreign_key: :parent_id,
    foreign_key_type: :integer

  schema "categories" do
    field(:name, :string)
    field(:parent_id, :integer)
    many_to_many(:answers, WordSolverDal.Answers.Answer, join_through: "answers_categories")
    timestamps()
  end

  @required [:name]
  @optional [:parent_id]

  def changeset(category, attrs) do
    category
    |> cast(attrs, @required ++ @optional)
    |> validate_required(@required)
    |> validate_length(:name, min: 3)
    |> unique_constraint(:name, name: :unique_categories_name_parent_id_null)
    |> unique_constraint(:name, name: :unique_categories_name_parent_id)
  end
end

The db throws a constraint error if a user tries to delete a record that has children due to the foreign key constraint on :parent_id.

constraint error when attempting to delete struct:

    * "categories_parent_id_fkey" (foreign_key_constraint)

If you would like to stop this constraint violation from raising an
exception and instead add it as an error to your changeset, please
call `foreign_key_constraint/3` on your changeset with the constraint
`:name` as an option.

This error gives advice on how to handle the error without raising an exception but I don’t see how this could work. As I understand it, foreign_key_constraint/3 is typically used for insert/update change sets.

How can I attempt a delete and not raise an exception as described? Or should I just rescue the error?

Marked As Solved

ibarch

ibarch

Maybe something like this would work?

defmodule WordSolverDal.Categories.Category do
  schema "categories" do
    has_many :descendant_categories, __MODULE__, foreign_key: :parent_id
  end
end

def delete_category(category) do
  category
  |> Ecto.Changeset.change()
  |> Ecto.Changeset.no_assoc_constraint(:descendant_categories,
    name: "categories_parent_id_fkey",
    message: "there is descendant categor[y|ies] associated with this one"
  )
  |> Repo.delete()
end

Also Liked

kokolegorille

kokolegorille

Ok, it’s a plugin from here…

https://github.com/coryodaniel/arbor

You need to define something like this…

  schema "categories" do
    ...
    belongs_to :parent, __MODULE__
    has_many :categories, __MODULE__

    timestamps
  end

otherwise it doesn’t know what categories are

=> and add foreign key, as @ibarch said

sharkmyster

sharkmyster

This worked. Thank you.

Where Next?

Popular in Questions Top

dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127089 1222
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement