improvement: add exclude_upsert_actions configuration

this allows for upserting records that factor in archived records.

Most commonly, this would be seen as a "create or unarchive" action,
so you'd add `change set_attribute(:archived_at, nil)`
This commit is contained in:
Zach Daniel 2024-07-18 11:26:14 -04:00
parent c23e6de7c6
commit 8612b41155
4 changed files with 36 additions and 2 deletions

View file

@ -3,7 +3,8 @@ spark_locals_without_parens = [
attribute: 1, attribute: 1,
base_filter?: 1, base_filter?: 1,
exclude_destroy_actions: 1, exclude_destroy_actions: 1,
exclude_read_actions: 1 exclude_read_actions: 1,
exclude_upsert_actions: 1
] ]
[ [

View file

@ -3,7 +3,10 @@ defmodule AshArchival.Resource.Changes.FilterArchivedForUpserts do
use Ash.Resource.Change use Ash.Resource.Change
def change(changeset, _, _) do def change(changeset, _, _) do
if changeset.context.private[:upsert?] && excluded_actions =
AshArchival.Resource.Info.archive_exclude_upsert_actions!(changeset.resource)
if changeset.action.name not in excluded_actions && changeset.context.private[:upsert?] &&
!AshArchival.Resource.Info.archive_base_filter?(changeset.resource) do !AshArchival.Resource.Info.archive_base_filter?(changeset.resource) do
attribute = AshArchival.Resource.Info.archive_attribute!(changeset.resource) attribute = AshArchival.Resource.Info.archive_attribute!(changeset.resource)
Ash.Changeset.filter(changeset, expr(is_nil(^ref(attribute)))) Ash.Changeset.filter(changeset, expr(is_nil(^ref(attribute))))

View file

@ -20,6 +20,13 @@ defmodule AshArchival.Resource do
A read action or actions that should show archived items. They will not get the automatic `is_nil(archived_at)` filter. A read action or actions that should show archived items. They will not get the automatic `is_nil(archived_at)` filter.
""" """
], ],
exclude_upsert_actions: [
type: {:wrap_list, :atom},
default: [],
doc: """
A create action or actions that should not filter archived records out while upserting.
"""
],
exclude_destroy_actions: [ exclude_destroy_actions: [
type: {:wrap_list, :atom}, type: {:wrap_list, :atom},
default: [], default: [],

View file

@ -67,11 +67,13 @@ defmodule ArchivalTest do
archive do archive do
archive_related([:comments]) archive_related([:comments])
exclude_read_actions :all_posts exclude_read_actions :all_posts
exclude_upsert_actions :upsert
end end
actions do actions do
default_accept(:*) default_accept(:*)
defaults([:create, :read, :update, :destroy]) defaults([:create, :read, :update, :destroy])
create(:upsert)
read(:all_posts) read(:all_posts)
end end
@ -225,6 +227,27 @@ defmodule ArchivalTest do
|> Ash.read!() |> Ash.read!()
end end
test "upserts do consider archived records if the create action is excluded" do
post =
Post
|> Ash.Changeset.for_create(:create, %{name: "fred"})
|> Ash.create!()
assert :ok = post |> Ash.destroy!()
Post
|> Ash.Changeset.for_create(:upsert, %{name: "fred"},
upsert?: true,
upsert_identity: :unique_name
)
|> Ash.create!()
assert [_] =
Post
|> Ash.Query.for_read(:all_posts)
|> Ash.read!()
end
test "destroying a record archives any `archive_related` it has configured" do test "destroying a record archives any `archive_related` it has configured" do
post = post =
Post Post