elixir - 为整个协会构建变更集
问题描述
我在这里读到了cast_assoc/3。但是文档看起来很混乱。我想single changeset for the entire association
在一个事务中构建并执行它以进行更新。这是我的模型;
defmodule User do
use Gallery.Web, :model
schema "users" do
field(:name, :string)
field(:occupation, :string)
has_many(:paintings, Painting)
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [ :name, :occupation ])
|> validate_required([:name, :occupation])
end
end
defmodule Painting do
use Gallery.Web, :model
schema "paintings" do
field(:name, :string)
belongs_to(:users, User)
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [ :name ])
|> validate_required([:name])
end
end
这是我要构建的单个变更集的数据
data= %User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 4606,
name: "Test",
occupation: "Artist",
paintings: [
%Painting{
__meta__: #Ecto.Schema.Metadata<:loaded, "paintings">,
user_id: 4606,
id: 1515,
name: "philip"
},
%Painting{
__meta__: #Ecto.Schema.Metadata<:loaded, "paintings">,
user_id: 4606,
id: 1516,
name: "john"
}
]
}
有什么建议么?
谢谢
解决方案
要使变更集正常工作,您的数据需要是纯映射而不是结构(就好像您从参数中获取的一样)。
如果您只想插入具有多幅绘画的用户,您需要:
- 摆脱结构
- 摆脱 ids(在插入的情况下,它们是动态创建的)
- 有一个
cast_assoc
用户变更集
像这样:
data = %{
name: "Test",
occupation: "Artist",
paintings: [
%{
name: "philip"
},
%{
name: "john"
}
]
}
%User{}
|> User.changeset(data)
|> Repo.insert
如果您还想以这种方式更新内容,它会变得更加复杂。目前尚不清楚中的绘画列表是否data
应该更新现有的绘画,添加新的或删除所有以前的绘画并将它们替换为data
. 我个人不建议使用嵌套变更集进行更新。https://hexdocs.pm/ecto/Ecto.Changeset.html#cast_assoc/3
澄清后更新:
要更新所有到位的绘画,您还需要做两件事。你需要:
- 预加载画作
- 在数据中有绘画ID
像这样:
data = %{
name: "Test",
occupation: "Artist",
paintings: [
%{
id: 1,
name: "philip"
},
%{
id: 2,
name: "john"
}
]
}
User
|> Repo.get_by(id: user_id)
|> Repo.preload(:paintings)
|> User.changeset(data)
|> Repo.update
你不需要使用Multi
. 这将是一笔交易。使用Repo
一次模块通常表示一次数据库操作。
所有的魔法都发生在paintings: [...]
. 根据文档,您有四种情况:
- 如果参数不包含ID,则参数数据将通过新结构传递到changeset/2,成为插入操作
- 如果参数包含一个 ID 并且没有与该 ID 关联的子节点,则参数数据将通过新结构传递到 changeset/2 并成为插入操作
- 如果参数包含一个 ID 并且有一个与该 ID 关联的子节点,则参数数据将使用现有结构传递到 changeset/2 并成为更新操作
- 如果有一个带有 ID 的关联子节点并且其 ID 未作为参数给出,则将调用该关联的 :on_replace 回调(请参阅模块文档中的“替换时”部分)
您对第三种情况下的更新感兴趣。如果你没有通过所有的画,data
你可能还会对第四个感兴趣。
推荐阅读
- python - 将 python flask 项目部署到网站中
- python - 熊猫:过滤或分组然后转换以选择最后一行
- r - 我的 shinydashboard 应用程序可以在我的机器上运行,但不能在 shinyapps.io 上运行
- javascript - 从一列的最后一行复制到电子表格的末尾(每次可变数字)
- python - 如何使用用户输入打破 while 循环
- adal - 获取 Exchange 命令行管理程序 cmdlet 的 OAuth2 访问令牌
- flutter - 保存列表的最佳方法是什么
本地,以便在重新打开应用程序时可以再次读取? - windows - Windows 10 Home:无法使用 Docker 访问“localhost:8000”
- angular - 如果我的方法返回的输出正确,为什么这个 Jasmine 单元测试总是失败(测试 Angular 组件)?
- android - 使用 Fragments 时,首选项不显示