grufino

grufino

Checking foreign key constraint when attempting to delete structure in has_many association

Hello,

I have a User structure that can have multiple accounts (has_many) and can be in multiple team through this accounts (many to many), as you can see below:

schema "user" do
    ...

    has_many :accounts, Account

    many_to_many(
      :teams,
      Team,
      join_through: Account
    )

    timestamps()
  end

And since I’m building basic CRUD operations for all entities of my application, I need to tell the user why he can’t delete his User (because there are still associated Accounts to it). But I can’t find a way to do this without try catching this way:

   try do
      Repo.delete(user)
    rescue
      Ecto.ConstraintError ->
        {:error, "In order to delete an user, you must first delete it's associated accounts"}
    end

But this is bad for 2 reasons, first is that it’s not standard that we use in our applications try catch (or erlang world), and second is that if I have more than one foreign constraint in any of my entities, I can’t tell which of them resulted in error.

I have tried all the possible ways found in documentation, for example:

on deletion:

Repo.get(User, user.id)
    |> Ecto.Changeset.change
    |> Ecto.Changeset.no_assoc_constraint(:accounts)
    |> Repo.delete()

on changeset validation:

user
|> Ecto.Changeset.no_assoc_constraint(:accounts)

user
|> foreign_key_constraint(:accounts, name: "johan_sports_team_users_user_id_9294a0f7_fk_auth_user_id")

I tried many variations of this, but nothing seems to help, in the end I always get:

** (Ecto.ConstraintError) constraint error when attempting to delete struct:

     * johan_sports_team_users_user_id_9294a0f7_fk_auth_user_id (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.

 The changeset has not defined any constraint.

Does anyone know a better solution for this?

First Post!

lucaong

lucaong

Honestly I am not an Ecto expert, but it seems to me that what you do should work:

user
|> Ecto.Changeset.change
|> Ecto.Changeset.no_assoc_constraint(:accounts)
|> Repo.delete

My only doubt is that you might have to specify the name of the foreign key, like Ecto.Changeset.no_assoc_constraint(:accounts, name: "johan_sports_team_users_user_id_9294a0f7_fk_auth_user_id"), if it was not automatically generated with references when creating the accounts table (it seems not, as the auto-generated name would be "#{table}_#{column}_fkey").

Where Next?

Popular in Questions Top

logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
Kagamiiiii
Student & New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
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
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement