Reputation: 1044
There are two models: resource and metadata:
defmodule Myapp.Repo.Migrations.CreateResources do
use Ecto.Migration
def change do
create table(:resources) do
add :name, :string
add :parent_id, references(:resources, on_delete: :delete_all)
timestamps
end
create index(:resources, [:parent_id])
end
end
defmodule Myapp.Repo.Migrations.CreateMetadata do
use Ecto.Migration
def change do
create table(:metadata) do
add :size, :integer
add :resource_id, references(:resources)
timestamps
end
create index(:metadata, [:resource_id])
end
end
schema "resources" do
field :name, :string
belongs_to :parent, Myapp.Resource
has_one :metadata, Myapp.Metadata, on_delete: :delete_all
has_many :childs, Myapp.Resource, foreign_key: :parent_id, on_delete: :delete_all
timestamps()
end
schema "metadata" do
field :size, :integer
belongs_to :resource, Myapp.Resource
timestamps()
end
resource can have children, which parent_id = id. also has a resource metadata. Table Metadata has resource_id column. Now, I want to delete the resource with the remove all his children, and all associated metadata. when I write
Repo.delete resource
I get an error:
[error] #PID<0.441.0> running Myapp.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /resources/%2Fdocs%2Ftest
** (exit) an exception was raised:
** (Postgrex.Error) ERROR (foreign_key_violation): update or delete on table "resources" violates foreign key constraint "metadata_resource_id_fkey" on table "metadata"
table: metadata
constraint: metadata_resource_id_fkey
Key (id)=(3) is still referenced from table "metadata".
that appears only when triggered to remove metadata from a resource children. If I try to delete a resource that has no childrens, then everything is working correctly.
Apparently, does not cause the removal of the children required callbacks removing metadata, so Postgres an error.
Whether it is possible to solve this problem without suffering from resource_id metadata metadata_id resource and without starting a recursive manual removal of all the children of the resource?
Upvotes: 2
Views: 3528
Reputation: 116
:delete_all does not cascade to child records unless set via database migrations. To fix the problem make sure you change your metadata migration script line to
add :resource_id, references(:resources, on_delete: :delete_all)
Upvotes: 5