Ecto удалить ссылку базы данных

У меня есть 2 таблицы:

Пользователь:

id
username
password

unique_index username

(the schema has a has_many other)

другой:

id
user_id - references(:users)
foo

index user_id

(the schema has a belongs_to user)

в наборе изменений для "Другое" у меня есть этот

model
|> cast(params, @req, @opt)
|> foreign_key_constraint(:user_id)

Мое предположение в этот момент было "Другой" ecto-моделью требует, чтобы "Пользователь" был связан с ним, чтобы существовать (это то, что я хочу)

Но мое второе предположение заключалось в том, что если я удалю запись "Пользователь", все связанные с ней записи "Другие" будут удалены (с помощью Cascade delete)

Что на самом деле происходит, у меня есть Ecto.ConstraintError при попытке удалить запись "Пользователь" (я предполагаю, потому что есть "Другая" запись, связанная с этим пользователем)

Итак, как бы я начал работать так, как хочу:

  • "Пользователь" может быть создан автономно
  • "Другой" может быть создан, но должен принадлежать "пользователю"
  • Когда удаляется "другое", это ничего не влияет на
  • Когда "пользователь" удален, он также удаляет все связанные с ним "другие" записи

По существу Cascade Delete для пользователя для любых элементов, которые ссылаются на него

Ответы

Ответ 1

Вы можете сделать это так, как вы указали в своей схеме, используя:

has_many :other, Project.Other, on_delete: :delete_all

Однако вам может быть лучше сделать это при переносе с помощью references/2:

create table(:others) do
  add :user_id, references(:users, on_delete: :delete_all)
end

Это будет использовать ограничения внешнего ключа базы данных и упоминается в документах has_many:

: on_delete - действие, выполняемое ассоциациями при удалении родительской модели. Может быть: ничего (по умолчанию),: nilify_all и: delete_all. Обратите внимание: on_delete также может быть установлен при миграции при создании ссылки. Если поддерживается, предпочтительнее использовать базу данных через миграции

Вы можете изменить существующий индекс следующим образом:

drop_if_exists index(:others, [:user_id])
alter table(:others) do
  modify :user_id, references(:users, type: :uuid, on_delete: :delete_all)
end

Ответ 2

Я понял, на многих можно передать опцию on_delete

поэтому has_many выглядит следующим образом

has_many :other, Project.Other, on_delete: :delete_all

Документы очень полезны: p

https://hexdocs.pm/ecto/Ecto.Schema.html#has_many/3