Phoenix控制器中的递归更新功能

时间:2018-09-18 06:37:24

标签: recursion elixir phoenix-framework

我有一个模型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

1 个答案:

答案 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