Created
April 16, 2022 15:04
-
-
Save zachdaniel/74104b1e1d80c65d8ca4684e0bfd91fe to your computer and use it in GitHub Desktop.
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.Extensions.Archive.Transformers.SetupArchival do | |
@moduledoc "Sets up the required resource structure for archival" | |
use Ash.Dsl.Transformer | |
@after_transformers [ | |
Ash.Resource.Transformers.SetPrimaryActions | |
] | |
@before_transformers [ | |
Ash.Resource.Transformers.DefaultAccept, | |
Ash.Resource.Transformers.SetTypes | |
] | |
alias Ash.Dsl.Transformer | |
def transform(resource, dsl_state) do | |
if Ash.Resource.Info.embedded?(resource) || !MyApp.Extensions.Archive.archive?(resource) do | |
{:ok, dsl_state} | |
else | |
dsl_state | |
|> add_archived_at() | |
|> update_destroy_actions() | |
|> add_base_filter() | |
|> add_base_filter_sql() | |
end | |
end | |
def after?(transformer) when transformer in @after_transformers, do: true | |
def after?(_), do: false | |
def before?(transformer) when transformer in @before_transformers, do: true | |
def before?(_), do: false | |
defp add_archived_at(dsl_state) do | |
with {:ok, archived_at} <- | |
Transformer.build_entity(Ash.Resource.Dsl, [:attributes], :attribute, | |
name: :archived_at, | |
type: :utc_datetime_usec, | |
private?: true, | |
allow_nil?: true | |
) do | |
{:ok, Transformer.add_entity(dsl_state, [:attributes], archived_at)} | |
end | |
end | |
defp update_destroy_actions({:ok, dsl_state}) do | |
dsl_state | |
|> Transformer.get_entities([:actions]) | |
|> Enum.filter(&(&1.type == :destroy)) | |
|> Enum.reduce({:ok, dsl_state}, fn destroy_action, {:ok, dsl_state} -> | |
with {:ok, set_archived_at} <- | |
Transformer.build_entity(Ash.Resource.Dsl, [:actions, :destroy], :change, | |
change: | |
Ash.Resource.Change.Builtins.set_attribute(:archived_at, &DateTime.utc_now/0) | |
) do | |
new_action = %{ | |
destroy_action | |
| soft?: true, | |
changes: [set_archived_at | destroy_action.changes] | |
} | |
{:ok, | |
Transformer.replace_entity( | |
dsl_state, | |
[:actions], | |
new_action, | |
&(&1.name == destroy_action.name) | |
)} | |
end | |
end) | |
end | |
defp update_destroy_actions({:error, error}), do: {:error, error} | |
defp add_base_filter({:ok, dsl_state}) do | |
case Transformer.get_option(dsl_state, [:resource], :base_filter) do | |
nil -> | |
{:ok, Transformer.set_option(dsl_state, [:resource], :base_filter, is_nil: :archived_at)} | |
value -> | |
{:ok, | |
Transformer.set_option(dsl_state, [:resource], :base_filter, | |
and: [[is_nil: :archived_at], value] | |
)} | |
end | |
end | |
defp add_base_filter({:error, error}) do | |
{:error, error} | |
end | |
defp add_base_filter_sql({:ok, dsl_state}) do | |
case Transformer.get_option(dsl_state, [:postgres], :base_filter_sql) do | |
nil -> | |
{:ok, | |
Transformer.set_option(dsl_state, [:postgres], :base_filter_sql, "archived_at IS NULL")} | |
value -> | |
{:ok, | |
Transformer.set_option( | |
dsl_state, | |
[:postgres], | |
:base_filter_sql, | |
"archived_at IS NULL and (#{value})" | |
)} | |
end | |
end | |
defp add_base_filter_sql({:error, error}) do | |
{:error, error} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment