更新Ecto变更集关联

问题描述 投票:0回答:1

我有一个具有has_many关联的Ecto架构设置。我希望能够动态添加/删除关联,保持初始关联。

我已经尝试使用Ecto.Changeset.put_assoc/4并且在加载初始关联时起作用,但是每个后续调用都将覆盖初始关联。

change_one = Changeset.put_assoc(changeset, :foo_assocs, [%{index: 1}])
...
foo_assocs: [
  #Ecto.Changeset<
    action: :insert,
    changes: %{index: 1},
    errors: [],
    data: #Linker.CustomForms.FooAssoc<>,
    valid?: true
  >
]
...

然后,如果我再次使用另一个相关记录调用它来添加:

change_two = Changeset.put_assoc(changeset_one, :foo_assocs, [%{index: 2}])
...
foo_assocs: [
  #Ecto.Changeset<
    action: :insert,
    changes: %{index: 2},
    errors: [],
    data: #Linker.CustomForms.FooAssoc<>,
    valid?: true
  >
]
...

我的第一张唱片被覆盖了。

elixir phoenix-framework ecto
1个回答
1
投票

这是put_assoc\4的预期行为,因为它旨在使用完整的数据集。实际上你的问题在Ecto docs中有很好的描述:https://hexdocs.pm/ecto/Ecto.Changeset.html#put_assoc/4-example-adding-a-comment-to-a-post

只要具有匹配的主键,就可以给出映射或关键字列表以更新关联数据。例如,put_assoc(changeset,:comments,[%{id:1,title:“changed”}])将找到注释:id为1并更新其标题。如果不存在具有此ID的注释,则即时创建一个。由于只给出了一条评论,因此将替换任何其他相关评论。

因此,您可以将现有数据与新数据合并并使用put_assoc\4,或者您可以处理您的单个关联,例如以下示例,其中您设置了您孩子的关联

changeset = %__MODULE__{} |> has_many(:foo_assoc, [%{index: 1}])

%FooChild{index: 2}
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:parent, changeset)
|> Repo.insert!()

但我建议阅读上面的链接,了解如何使用put_assoc/4has_many的更多详细说明。

© www.soinside.com 2019 - 2024. All rights reserved.