Skip to content

Commit

Permalink
feat(ignore_actions): allow to ignore actions by configuration (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbaertschi authored Sep 5, 2024
1 parent 6c6d772 commit 7d390b8
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 3 deletions.
1 change: 1 addition & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ spark_locals_without_parens = [
change_tracking_mode: 1,
define_attribute?: 1,
domain: 1,
ignore_actions: 1,
ignore_attributes: 1,
include_versions?: 1,
mixin: 1,
Expand Down
1 change: 1 addition & 0 deletions documentation/dsls/DSL:-AshPaperTrail.Resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ A section for configuring how versioning is derived for the resource.
| [`attributes_as_attributes`](#paper_trail-attributes_as_attributes){: #paper_trail-attributes_as_attributes } | `list(atom)` | `[]` | A set of attributes that should be set as attributes on the version resource, instead of stored in the freeform `changes` map attribute. |
| [`change_tracking_mode`](#paper_trail-change_tracking_mode){: #paper_trail-change_tracking_mode } | `:snapshot \| :changes_only \| :full_diff` | `:snapshot` | Changes are stored in a map attribute called `changes`. The `change_tracking_mode` determines what's stored. See the getting started guide for more. |
| [`ignore_attributes`](#paper_trail-ignore_attributes){: #paper_trail-ignore_attributes } | `list(atom)` | `[]` | A list of attributes that should be ignored. Typically you'll want to ignore your timestamps. The primary key is always ignored. |
| [`ignore_actions`](#paper_trail-ignore_actions){: #paper_trail-ignore_actions } | `list(atom)` | `[]` | A list of actions that should not produce new versions. By default, no actions are ignored. |
| [`mixin`](#paper_trail-mixin){: #paper_trail-mixin } | `atom \| mfa` | | A module that defines a `using` macro or {module, function, arguments} tuple that will be mixed into the version resource. |
| [`on_actions`](#paper_trail-on_actions){: #paper_trail-on_actions } | `list(atom)` | | Which actions should produce new versions. By default, all create/update actions will produce new versions. |
| [`reference_source?`](#paper_trail-reference_source?){: #paper_trail-reference_source? } | `boolean` | `true` | Whether or not to create a foreign key reference from the version to the source. This should be set to `false` if you are allowing actual deletion of data. Only relevant for resources using the AshPostgres data layer. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use Ash.Resource,
change_tracking_mode :changes_only # default is :snapshot
store_action_name? true # default is false
ignore_attributes [:inserted_at, :updated_at] # the primary keys are always ignored
ignore_actions [:destroy] # default is []
end
```

Expand Down
7 changes: 4 additions & 3 deletions lib/resource/changes/create_new_version.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ defmodule AshPaperTrail.Resource.Changes.CreateNewVersion do

@impl true
def change(changeset, _, _) do
if changeset.action_type in [:create, :destroy] ||
(changeset.action_type == :update &&
changeset.action.name in AshPaperTrail.Resource.Info.on_actions(changeset.resource)) do
if changeset.action.name not in AshPaperTrail.Resource.Info.ignore_actions(changeset.resource) &&
(changeset.action_type in [:create, :destroy] ||
(changeset.action_type == :update &&
changeset.action.name in AshPaperTrail.Resource.Info.on_actions(changeset.resource))) do
create_new_version(changeset)
else
changeset
Expand Down
5 changes: 5 additions & 0 deletions lib/resource/info.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ defmodule AshPaperTrail.Resource.Info do
Spark.Dsl.Extension.get_opt(resource, [:paper_trail], :ignore_attributes, [])
end

@spec ignore_actions(Spark.Dsl.t() | Ash.Resource.t()) :: [atom]
def ignore_actions(resource) do
Spark.Dsl.Extension.get_opt(resource, [:paper_trail], :ignore_actions, [])
end

@spec mixin(Spark.Dsl.t() | Ash.Resource.t()) :: {module, atom, list} | module | nil
def mixin(resource) do
Spark.Dsl.Extension.get_opt(resource, [:paper_trail], :mixin, nil)
Expand Down
7 changes: 7 additions & 0 deletions lib/resource/resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ defmodule AshPaperTrail.Resource do
A list of attributes that should be ignored. Typically you'll want to ignore your timestamps. The primary key is always ignored.
"""
],
ignore_actions: [
type: {:list, :atom},
default: [],
doc: """
A list of actions that should not produce new versions. By default, no actions are ignored.
"""
],
mixin: [
type: {:or, [:atom, :mfa]},
default: nil,
Expand Down
21 changes: 21 additions & 0 deletions test/ash_paper_trail_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -508,4 +508,25 @@ defmodule AshPaperTrailTest do
assert is_nil(updated_version.id)
end
end

describe "ignore_actions" do
test "no new version is created on destroy" do
assert %{subject: "subject", body: "body"} =
article = Articles.Article.create!("subject", "body")

assert :ok = Articles.Article.destroy!(article)

versions = Ash.read!(Articles.Article.Version) |> Enum.sort_by(& &1.version_inserted_at)

assert [
%{
subject: "subject",
body: "body",
version_action_type: :create
}
] = versions

refute Enum.any?(versions, &(&1.version_action_type == :destroy))
end
end
end
1 change: 1 addition & 0 deletions test/support/articles/article.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ defmodule AshPaperTrail.Test.Articles.Article do
paper_trail do
primary_key_type :integer
attributes_as_attributes [:subject, :body]
ignore_actions [:destroy]
change_tracking_mode :snapshot
end

Expand Down

0 comments on commit 7d390b8

Please sign in to comment.