web-dev-qa-db-ja.com

参照されたデータベースレコードを削除する

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)

この時点での私の想定は、「その他」の外部モデルでは、「ユーザー」が存在するためにそれに関連付けられる必要があるということでした(これが私が望んでいることです)。

しかし、私の2番目の前提は、「ユーザー」レコードを削除すると、関連するすべての「その他」レコードが(カスケード削除によって)削除されることでした。

「ユーザー」レコードを削除しようとすると、Ecto.ConstraintErrorが実際に発生します(そのユーザーに「その他」のレコードが関連付けられていると想定しています)

それで、私が望むようにそれを機能させるにはどうすればいいですか?

  • 「ユーザー」はスタンドアロンで作成できます
  • 「その他」を作成できますが、「ユーザー」に属している必要があります
  • 「その他」が削除されても、他には影響しません
  • 「ユーザー」を削除すると、関連する「その他」のレコードもすべて削除されます

基本的に、ユーザーを参照するすべてのアイテムのカスケード削除

20
TheStoneFox

スキーマで指定した方法で次のように実行できます。

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-親モデルが削除されたときに関連付けに対して実行されるアクション。 :nothing(デフォルト)、: 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
49
Gazler

私はそれを理解しました、あなたはon_deleteオプションを渡すことができる多くのものを持っています

だからhas_manyはこのようになります

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

ドキュメントはかなり役に立ちます:p

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

7
TheStoneFox