How to Delete A Table That Contains a "has many" Value Without Deleting Children

From ElixirBlocks
Jump to: navigation, search

If you have a table that you are trying to delete and the table contains a has_many relationship, you may get an error similar to the one below when you attempt to delete the parent table.

Error

constraint error when attempting to delete struct:
    * item_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.

The changeset has not defined any constraint.

Solution

A possible solution is to edit the schema to use :on_delete to :nilify_all.

on_delete determines how your table reacts to deletion.

Example:

defmodule App.Groups.Group do
  use Ecto.Schema
  import Ecto.Changeset
  
  alias App.TestBeds.TestBed   
  schema "groups" do
    field :name, :string
    has_many :testbeds, TestBed, on_delete: :nilify_all  # When Group is deleted, the testbeds are left alone and are not deleted with it
    timestamps()
  end

  @doc false
  def changeset(group, attrs) do
    group
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

on_delete has other ooptions that may be useful to you. https://hexdocs.pm/ecto/Ecto.Schema.html#has_many/3-options