zer3f

zer3f

Hello,

I am using ash_papertrail for audit logs. But I have setup 2 actors like this:

paper_trail do
    # default is :uuid
    primary_key_type(:uuid_v7)
    # default is :snapshot
    change_tracking_mode(:changes_only)
    # default is false
    store_action_name?(true)
    # the primary keys are always ignored
    ignore_attributes([:inserted_at, :updated_at])
    # default is []
    ignore_actions([:destroy])

    store_action_inputs?(true)

    store_resource_identifier?(true)

# Passed through actor
    belongs_to_actor(:user, Mgx.Accounts.User, domain: Mgx.Accounts)

# Have existing relastionship
    belongs_to_actor(:company_information, Mgx.Company.CompanyInformation, domain: Mgx.Company)
  end

So in the LiveView, I am passing actor as current_user like this which works, but user_id,

form =
      company_information
      |> AshPhoenix.Form.for_update(:update_company_documents,
        as: "company-information",
        forms: [auto?: true],
        actor: socket.assigns.current_user
      )

Since actor can be only one, is there is any way I can pass company_information_id ?
image. Or any other way, by removing actor looked into mixin, But didn’t understand properly. I tried putting company_information_id in the params but didn’t work either :slight_smile:

Appreciate for any help. Thank you

Showing Posts 1 to 10

zachdaniel

zachdaniel

Creator of Ash

There is only ever one actor as you say, and I don’t think there is way to pass inputs or data through to the version itself. Can you describe more specifically what you’d like to accomplish? You could try adding a “last_updated_by_company” relationship to the main resource, at which point each version would have that available in its changes, if that is what you’re looking for.

zer3f

zer3f OP

Sure,

I have an update action from the company_information resource that manages company_documents. This is the action:

update :update_company_documents do
      argument :company_documents, {:array, :map}

      require_atomic? false

      change manage_relationship(:company_documents, type: :direct_control)
    end

I think since because of manage_relationship, I can not find audit version record in the relevant table. So i added paper_trail section in the company_documents resource so that i can track the changes.

The business logic is, a company_information can have many_to_many with users, but company_documents belongs_to company_information only, not users, Although I can get the to which company he made through company_inforamtion and company_documents relationship, I thought it might be better if we just add the company_information_id and get direct queries with user_id and company_information_id, without extra join.

zachdaniel

zachdaniel

Creator of Ash

Hmm…you can use the version mixin to add an extra attribute company_information_id, and a change to look it up for the given inputs.

defmodule YourMixin do
  defmacro __using__(_) do
    relationships do
      belongs_to ...
    end

    changes do
       change ..., on: [:create]
    end
  end
end
zer3f

zer3f OP

Sorry Zach, I tried what you said, but somehow not even new record inserting into the database, maybe syntax issue?

defmodule Mgx.PaperTrail.CompanyInformationIdMixin do
  use Ash.Resource

  defmacro __using__(_opts) do
    quote do
      relationships do
        belongs_to :company_information, Mgx.Company.CompanyInformation
      end

      changes do
        # Get the argument from the ash changeset, company information id, and set it in the changeset
        change fn changeset, _context ->
                 company_information_id =
                   Ash.Changeset.fetch_argument(changeset, :company_information_id)

                 Ash.Changeset.force_change_attribute(
                   changeset,
                   :company_information_id,
                   company_information_id
                 )
               end,
               on: [:create]
      end
    end
  end
end

This is how I am able to use paper trail:

paper_trail do
    primary_key_type(:uuid_v7)
    change_tracking_mode(:changes_only)
    store_action_name?(true)
    ignore_attributes([:inserted_at, :updated_at])
    ignore_actions([:destroy])

    belongs_to_actor(:user, Mgx.Accounts.User, domain: Mgx.Accounts)

    mixin(Mgx.PaperTrail.CompanyInformationIdMixin)
  end

and tried to put in company_information_id in the params like this

def handle_event("save", %{"company-information" => params}, socket) do
    params =
      params
      |> Map.put("company_information_id", socket.assigns.company_information.id)
# ........

Now even the new record is not inserting.

zachdaniel

zachdaniel

Creator of Ash

Are you getting some kind of error?

zer3f

zer3f OP

No error. The save event is successful, as a well as relevant data (company_documents) in db. But I can’t see new version of audit log in the table

zachdaniel

zachdaniel

Creator of Ash

Can you try main of ash_paper_trail?

zer3f

zer3f OP

Yeah I tried to install from the main. It Still not working. This is the logs: Although I got error, where Ash.Changeset.fetch_argument gives tuple, Once i fixed and tried it, Now the the record are succesfully implemented but, company_information_id is still nil.
I also tried to put in the company_information_id in the nested form params, but no result i am getting company_information_id in the mixin

Mixin:

defmodule Mgx.PaperTrail.CompanyInformationIdMixin do
  use Ash.Resource

  defmacro __using__(_opts) do
    quote do
      relationships do
        belongs_to :company_information, Mgx.Company.CompanyInformation
      end

      changes do
        # Get the argument from the ash changeset, company information id, and set it in the changeset
        change fn changeset, _context ->
                 company_information_id =
                   Ash.Changeset.get_argument_or_attribute(changeset, :company_information_id)

                 dbg(company_information_id)

                 Ash.Changeset.force_change_attribute(
                   changeset,
                   :company_information_id,
                   company_information_id
                 )
               end,
               on: [:create]
      end
    end
  end
end

Here are the logs:

[(mgx 0.1.0) deps/ash_paper_trail/lib/resource/transformers/create_version_resource.ex:335: Mgx.Company.BusinessAddress.Version.change_0_generated_598ECEEE256D572A87FEABA91E2A2838/2]
company_information_id #=> nil

Params:

params #=> %{
  "business_address" => %{
    "_form_type" => "create",
    "_persistent_id" => "0",
    "_touched" => "company_information_id,_form_type,_persistent_id,_touched,_unused_city,_unused_country_code,_unused_postal_code,_unused_state,_unused_street,city,company_information_id,country_code,postal_code,state,street",
    "city" => "Bentley Dennis Plc",
    "company_information_id" => "653bdcc3-52eb-429d-b774-2cf646a72057",
    "country_code" => "Mccray Moss LLC",
    "postal_code" => "Lee Giles Traders",
    "state" => "Sullivan and Farley Associates",
    "street" => "Walters Conrad Traders"
  },
  "website" => "https://www.nuzejiha.mobi"
}

[debug] QUERY OK db=0.7ms idle=1973.5ms
begin []

Create Action:

create :create do
      primary? true
      accept [:company_information_id, :country_code, :state, :city, :street, :postal_code]
    end
zachdaniel

zachdaniel

Creator of Ash

Yeah, you won’t get the arguments from the main action call in the version mixin. You may have to run a query there to fetch the company_information_id based on the other attributes available to you there. Otherwise we would need to add some kind of feature where the version action gets context set on it like the parent changeset.

zer3f

zer3f OP

Thanks Zach, I already have context that has actor current_user that has company_information_id :smile:

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews