Ash FrameworkAF
Ash Framework6mo ago
17 replies
Shahryar

How to use `after_action` when soft delete is enabled in global `Change`

Hi, Sorry! I have a global change that i am using inside my many resources! the problem i have when i use soft delete Ash.destroy!(Ash.get!(MishkaCms.Runtime.Site, id)) it is not triggerd

It does not work
defmodule MishkaCms.Runtime.Resources.Changes.SendToOban do
  use Ash.Resource.Change

@impl true
def change(changeset, _opts, _context) do
  Ash.Changeset.after_action(changeset, fn changeset, record ->
    IO.inspect(changeset, label: "changeset==========")


But it works
defmodule MishkaCms.Runtime.Resources.Changes.SendToOban do
  use Ash.Resource.Change

@impl true
def change(changeset, _opts, _context) do
  IO.inspect(changeset, label: "changeset==========")
  Ash.Changeset.after_action(changeset, fn changeset, record ->


Is it way to use Archive destroy inside Ash.Changeset.after_action ?

By the way my config in my resource


postgres do
  table "sites"
  repo MishkaCms.Repo

  # Database-level optimization for archived records
  base_filter_sql "(archived_at IS NULL)"
  ...
  
 archive do
    # base_filter? false
    exclude_read_actions [:archived]
    exclude_destroy_actions [:permanent_destroy]
  end

changes do
  change {Changes.SendToOban, []}, on: [:create, :update, :destroy]
end


I have read this but i am using global Change
- https://hexdocs.pm/ash_archival/0.1.2/archival.html

Thank you in advance
Solution
So it could be that it uses the atomic callback depending on how you call your action and your atomic implementation isn't doing anything. But as your change only has an after_action and that's allowed in the context of atomics you can try this:

defmodule MishkaCms.Runtime.Resources.Changes.SendToOban do
  use Ash.Resource.Change

  @impl true
  def change(changeset, _opts, _context) do
    IO.inspect(changeset, label: "changeset==========")

    Ash.Changeset.after_action(changeset, fn changeset, record ->
      if changeset.action.type != :update or changeset.context[:changed?] do
        enqueue_job(changeset, record)
      end

      {:ok, record}
    end)
  end

  # UPDATED this function
  @impl true
  def atomic(changeset, opts, context) do
    {:ok, change(changeset, opts, context)}
  end

  if Code.ensure_loaded?(Mix) and Mix.env() == :test do
    defp enqueue_job(_changeset, _record) do
      :ok
    end
  else
    defp enqueue_job(changeset, record) do
      original_record = changeset.data

      # Get the old values with defaults
      old_data = %{
        active: Map.get(original_record, :active, false),
        precompile: Map.get(original_record, :precompile, false)
      }

      %{
        resource: inspect(changeset.resource),
        action: changeset.action.type,
        data:
          Ash.Resource.Info.attributes(changeset.resource)
          |> Enum.map(fn attr -> {attr.name, Map.get(record, attr.name)} end)
          |> Map.new(),
        old_data: old_data
      }
      |> MishkaCms.Runtime.Workers.RuntimeCompilerWorker.new()
      |> Oban.insert()
    end
  end
end
Was this page helpful?