我有一个具有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
>
]
...我的第一张唱片被改写了。
发布于 2019-04-08 18:04:32
这是put_assoc/4的预期行为,因为它打算处理完整的数据集。实际上,您的问题在Ecto docs: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/4和has_many的更详细说明。
https://stackoverflow.com/questions/55578784
复制相似问题