为具有嵌套关联的深层嵌套结构创建Ecto变更集

问题描述

请考虑以下架构:

schema "businesses" do
  ...
  has_many :contacts,Contact
  has_many :conversations,Conversation
  ...
end
schema "contacts" do
  ...
  belongs_to :business,Business
  has_one :conversation,Conversation
  ...
end
schema "conversations" do
  ...
  belongs_to :business,Business
  belongs_to :contact,Contact
  has_many :messages,Message
  ...
end
schema "messages" do
  belongs_to :conversation,Conversation
  belongs_to :contact,Contact
end

鉴于我拥有一个business结构,我该如何以一种处理关联的方式创建contactconversationmessage结构?

当排除messages部分时,以下工作。

business
|> Ecto.build_assoc(
  :contacts,%Contact{name: name,phone: phone}
)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(
  :conversation,%Conversation{business: business}
  |> Ecto.Changeset.change()
  |> Ecto.Changeset.cast_assoc(:business)
)
# |> Ecto.Changeset.put_assoc(:messages,[%Message{body: "hello"}])
|> Repo.insert()

由于没有注释到倒数第二行,Postgresql告诉我message应该有一个conversation_id,这是事实。怎么设置?

添加IO.inspect()

business
|> Ecto.build_assoc(
  :contacts,%Conversation{business: business}
  |> Ecto.Changeset.change()
  |> Ecto.Changeset.cast_assoc(:business)
)
  |> IO.inspect()
# |> Ecto.Changeset.put_assoc(:messages,[%Message{body: "hello"}])
|> Repo.insert()

表明在尝试设置messages关联之前,我们正在使用以下变更集:

#Ecto.Changeset<
  action: nil,changes: %{
    conversation: #Ecto.Changeset<action: :insert,changes: %{},errors: [],data: #Conversation<>,valid?: true>
  },data: #Contact<>,valid?: true

新创建的message是否可以与新创建的contact和新创建的conversation关联?

解决方法

这对ViewWillDisappear是可行的。

https://hexdocs.pm/ecto/Ecto.Multi.html