Now, what I need to do is, If I soft-delete FolderA, All it’s children folders and files down the line should be also be soft-deleted (updated archived value into true).
def soft_delete_folder(folder) do
folder
|> Repo.update_all(set: [archived: true])
|> case do
{:ok, _updated_folders} ->
# Soft deletes all folders in the folder
folder
|> Repo.preload(:folders)
|> Map.get(:folders)
|> Enum.each(&soft_delete_folder/1)
# Updates all files in the folder
Repo.update_all(from f in File, where: f.folder_id == ^folder.id, set: [archived: true])
_ ->
{:error, "Failed to soft delete folder and children."}
end
end
Somewhat of a hybrid and probably not really optimal, but it could be a start:
def delete_folder(%Folder{id: id}) do
folder_ids_query = """
WITH RECURSIVE folder_ids(id, folder_id) AS (
SELECT id, folder_id FROM folders WHERE id = $1
UNION ALL
SELECT t.id, t.folder_id FROM folders t INNER JOIN folder_ids c on c.id = t.folder_id
)
SELECT id FROM folder_ids
"""
{:ok, result} = Repo.query(folder_ids_query, [id])
folder_ids = List.flatten(result.rows)
Repo.transaction(fn ->
from(f in Folder, where: f.id in ^folder_ids, update: [set: [archived: true]])
|> Repo.update_all([])
from(f in File, where: f.folder_id in ^folder_ids, update: [set: [archived: true]])
|> Repo.update_all([])
end)
end