Elixir 在EXTO中插入相关模型
我正在尝试插入发票结构及其关联的发票项。我能够插入发票数据,并调用匿名函数来验证、转换和插入每个项目。由于insert/2不生成退货,如果一个项目未通过验证或插入,我如何获取该项目的发票id,同时仍然能够回滚整个交易 我已将代码放入我自己的回购协议中,如下所示:Elixir 在EXTO中插入相关模型,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我正在尝试插入发票结构及其关联的发票项。我能够插入发票数据,并调用匿名函数来验证、转换和插入每个项目。由于insert/2不生成退货,如果一个项目未通过验证或插入,我如何获取该项目的发票id,同时仍然能够回滚整个交易 我已将代码放入我自己的回购协议中,如下所示: def insertassoc(params) do Repo.transaction(fn -> i = Invoice.changeset(params["data"], :create) if i.va
def insertassoc(params) do
Repo.transaction(fn ->
i = Invoice.changeset(params["data"], :create)
if i.valid? do
Repo.insert(i)
else
Repo.rollback(i.errors)
end
insert_include = fn k ->
c = InvoiceItem.changeset(k, :create)
if c.valid? do
Repo.insert(c)
else
Repo.rollback(c.errors)
end
end
for include <- params["includes"] do
insert_include.(Map.merge(include, %{"invoice_id" => ????}))
end
end)
end
没有太多的最新的例子,所以很抱歉,如果这些是noob问题;-)。有人有主意吗?我尝试将发票插入放在一个私有函数中,并使用一个case块来确定主事务是否应该回滚,但我也不知道如何从中获取发票id。
Repo.insert/1
实际上返回您刚才插入的模型。您还希望尽可能地将验证与事务处理分离。我建议如下:
invoice = Invoice.changeset(params["data"], :create)
items = Enum.map(params["includes"], &InvoiceItem.changeset(&1, :create))
if invoice.valid? && Enum.all?(items, & &1.valid?) do
Repo.transaction fn ->
invoice = Repo.insert(invoice)
Enum.map(items, fn item ->
item = Ecto.Changeset.change(item, invoice_id: invoice.id)
Repo.insert(item)
end)
end
else
# handle errors
end
在Ecto 2.0中,您将执行以下操作:
%My.Invoice{}
|> Ecto.Changeset.change
|> Ecto.Changeset.put_assoc(:invoice_items, [My.InvoiceItem.changeset(%My.InvoiceItem{}, %{description: "bleh"})])
|> My.Repo.insert!
(公认的答案适用于2.0之前的版本,Valim在该答案的评论中提到存在
put_assoc
)谢谢,这更优雅。顺便说一句,对于那些将要使用它的人来说,我是如何处理错误以将它们编码成JSON的:errors=Enum.map(items,&(&1.errors))|>Enum.into([invoice.errors])|>Enum.map(&(Enum.into(&1,%{})){:errors,errors}
API现在已经更改,因此Repo.insert
应该替换为Repo.insert
返回模型或在事务中引发错误。除此之外,Ecto现在还支持put_assoc
,它允许您更改父模式及其子模式,这将使上面的代码更清晰@JoséValim-请您详细说明put_assoc将如何简化代码?我试图同时插入一个模型及其关联。模型A有许多模型B。我在考虑为模型A和模型B创建变更集,并在put_assoc中提供模型A的变更集。不。没用。例如-csModelA=%ModelA{}}}>change}>ModelA.create_变更集(params)和csModelB=%ModelB{}}>change}>put_assoc(:ModelA,csModelA)|>ModelB.create_变更集。当添加模型B抱怨外键不存在时,会出现这种情况
%My.Invoice{}
|> Ecto.Changeset.change
|> Ecto.Changeset.put_assoc(:invoice_items, [My.InvoiceItem.changeset(%My.InvoiceItem{}, %{description: "bleh"})])
|> My.Repo.insert!