Last active
November 27, 2018 07:24
-
-
Save rockwood/78150119d8736234d048b98227423b26 to your computer and use it in GitHub Desktop.
Ecto Soft-Delete Pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyApp.ArchivePostScenario do | |
alias MyApp.Repo | |
alias Ecto.Multi | |
alias __MODULE__.Query | |
def run(options) do | |
post = Keyword.fetch!(options, :post) | |
archive_and_delete([ | |
comments: Query.comments(post), | |
views: Query.views(post), | |
posts: Query.posts(post), | |
]) | |
end | |
defp archive_and_delete(queries) do | |
Multi.new() | |
|> archive(queries) | |
|> delete(queries) | |
|> Repo.transaction() | |
|> case do | |
{:ok, result} -> {:ok, result} | |
{:error, step, _result, _changes_so_far} -> {:error, step} | |
end | |
end | |
defp archive(multi, queries) do | |
Enum.reduce(queries, multi, fn({name, query}, acc) -> | |
record_maps = query |> Query.select_plain_map() |> Repo.all() | |
Multi.insert_all(acc, "archive_#{name}", name, record_maps, prefix: :archive) | |
end) | |
end | |
defp delete(multi, queries) do | |
Enum.reduce(queries, multi, fn({name, query}, acc) -> | |
Multi.delete_all(acc, "delete_#{name}", query) | |
end) | |
end | |
defmodule Query do | |
import Ecto.Query | |
alias MyApp.{Blog} | |
def posts(post) do | |
from Blog.Post, where: [id: ^post.id] | |
end | |
def views(post) do | |
from Blog.View, where: [post_id: ^post.id] | |
end | |
def comments(post) do | |
from Blog.Comment, where: [post_id: ^post.id] | |
end | |
def select_plain_map(query = %{from: %{source: {_name, schema}}}) do | |
fields = schema.__schema__(:fields) | |
from record in query, select: map(record, ^fields) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment