我有一个模型Folder
,可以有“子文件夹”。每次更新文件夹时,子文件夹也必须更新。这是我创建递归更新功能的尝试:
def update(folder_id, params, context \\ "contracts") do
folder = get(folder_id, context, [:groups, :child_folders])
child_folders = folder.child_folders
case child_folders do
child_folders when length(child_folders) > 0 ->
for child_folder <- child_folders do
Contract.Folder.update(child_folder.id, params)
end
[] ->
params = build_folder_groups_params(params)
folder
|> build_changeset(params)
|> put_assoc_by_params(params, folder.context)
|> Repo.update()
end
end
子文件夹得到更新,但是我遇到了case子句匹配错误,并且当前文件夹没有得到更新。
编辑:
我将循环转换为Enum.reduce
。它对于第一组child_folders
正常工作,但不是递归的。我该如何递归?
def update(folder_id, params, context \\ "contracts") do
folder = get(folder_id, context, [:groups, child_folders: :groups])
child_folders = folder.child_folders
folder_group_params = Map.delete(params, "name")
multi = Enum.reduce(child_folders, Multi.new, fn child_folder, multi_accumulator ->
new_params =
folder_group_params
|> Map.update("folder_groups", [], fn groups ->
Enum.uniq(groups ++ Enum.map(child_folder.groups, &("#{&1.id}")))
end)
|> build_folder_groups_params
child_folder_changeset =
child_folder
|> build_changeset(new_params)
|> put_assoc_by_params(new_params, child_folder.context)
Multi.update(multi_accumulator, :folder, child_folder_changeset)
end)
Repo.transaction(multi)
params = build_folder_groups_params(params)
folder
|> build_changeset(params)
|> put_assoc_by_params(params, folder.context)
|> Repo.update()
end
答案 0 :(得分:0)
在case
子句中,只有两种可能的情况,列表为空或包含元素,因此可以将条件更改为
case length(child_folders) do
0 -> params = build_folder_groups_params(params)
folder
|> build_changeset(params)
|> put_assoc_by_params(params, folder.context)
|> Repo.update()
_ -> child_folders
|> Enum.Each(fn child_folder -> Contract.Folder.update(child_folder.id, params) end)
end