title: Recursive update function in Phoenix controller
body: <p>I have a model <code>Folder</code> which can have "child folders". Everytime a folder is updated, a child folder must be updated as well. This is my attempt in creating a recursive update function:</p>
  
  <pre><code>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) &gt; 0 -&gt;
        for child_folder &lt;- child_folders do
          Contract.Folder.update(child_folder.id, params)
        end
  
      [] -&gt;
        params = build_folder_groups_params(params)
  
        folder
        |&gt; build_changeset(params)
        |&gt; put_assoc_by_params(params, folder.context)
        |&gt; Repo.update()    
    end
  end
  </code></pre>
  
  <p>The child folders get updated but I get a case clause matching error and the current folder doesn't get updated.</p>
  
  <p>Edit:</p>
  
  <p>I converted the loop into an <code>Enum.reduce</code>. It works fine for the first set of <code>child_folders</code> but it is not recursive. How do I make this recursive?</p>
  
  <pre><code>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 -&gt;
              new_params =
                folder_group_params
                |&gt; Map.update("folder_groups", [], fn groups -&gt;
                    Enum.uniq(groups ++ Enum.map(child_folder.groups, &amp;("#{&amp;1.id}")))
                  end)
                |&gt; build_folder_groups_params
  
              child_folder_changeset =
                child_folder
                |&gt; build_changeset(new_params)
                |&gt; 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
    |&gt; build_changeset(params)
    |&gt; put_assoc_by_params(params, folder.context)
    |&gt; Repo.update()
  end
  </code></pre>