更新Ecto变更集关联

时间:2019-04-08 17:31:08

标签: elixir phoenix-framework ecto

我有一个具有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
  >
]
...

我的第一条记录被覆盖。

1 个答案:

答案 0 :(得分:1)

这是Power BI / add refresh button on report view的预期行为,因为它打算与完整数据集一起使用。实际上,您的问题在Ecto文档中得到了很好的描述:put_assoc\4

  

可以提供地图或关键字列表以将相关数据更新为   只要它们具有匹配的主键。例如,   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