Using ash-paper-trail together with AshUUID prefixed pk's

Hi There,

On the mission to find a ash friendly way to add versioning to my project. I found ash-paper-trail.
My requirements were:

  • postgres compatible
  • no additional database extensions
  • testing friendly (no workaround to run tests)
  • support to add versioning to single resources instead of all tables
  • option to only store the attributes which changed

after browsing a bit through the forum I found this post which gave me a great idea of whats possible and I started using ash-paper-trail because it ticks all the boxes.

After setting up things and migrating the database, I faced errors while executing my tests:

** (Ash.Error.Invalid) Input Invalid

     * Invalid value provided for version_source_id: got invalid prefixed term.

     "rec_02vbruyKluKnzDyCkFExo8"
     
     code: assert {:ok, %Record{} = _record} = Record.create(attrs)
     stacktrace:
       (ash 2.18.2) lib/ash/api/api.ex:2711: Ash.Api.unwrap_or_raise!/3
       (ash_paper_trail 0.1.0) lib/resource/changes/create_new_version.ex:93: AshPaperTrail.Resource.Changes.CreateNewVersion.build_notifications/2
       (ash_paper_trail 0.1.0) lib/resource/changes/create_new_version.ex:22: anonymous fn/2 in AshPaperTrail.Resource.Changes.CreateNewVersion.create_new_version/1
...

then I checked my resource definition:

...
  use Ash.Resource,
    data_layer: AshPostgres.DataLayer,
    extensions: [
      AshUUID,
      AshPaperTrail.Resource
    ]
...
  attributes do
    uuid_attribute :id, prefix: "rec"
    attribute :name, :string
    attribute :description, :string
    timestamps private?: false, writable?: false
  end

  paper_trail do
    change_tracking_mode :changes_only
    store_action_name? true
    ignore_attributes [:inserted_at, :updated_at]
  end
...

And I was wondering if the use of AshUUID and the prefixed primary key definition leads to the fact that I can’t use ash-paper-trail at all or if I missed the one hint to make it work in this case?
It would be really a shame if it would not work, because it’s such a smooth and nice integration compared to other solutions.

All the Best

I think I see the issue. We aren’t properly copying the type of the attribute that we use for version_source_id. Let me see what I can do.

okay, can you try out the main branch of ash_paper_trail?

oh wow… sure… I’ll try…

using {:ash_paper_trail, github: "ash-project/ash_paper_trail", branch: "main"}: it seems to be still the same problem.

thx anyway for jumping in so quickly! :slight_smile: well appriciated.

the resource I use, is very minimal, so from that side, no side effects should be expected:

defmodule App.Records.TestResource do
  @moduledoc false

  use Ash.Resource,
    data_layer: AshPostgres.DataLayer,
    extensions: [
      AshUUID,
      AshPaperTrail.Resource
    ]

  attributes do
    uuid_attribute :id, prefix: "baa"
    attribute :name, :string
    attribute :description, :string
    timestamps private?: false, writable?: false
  end

  paper_trail do
    change_tracking_mode :changes_only
    store_action_name? true
    ignore_attributes [:inserted_at, :updated_at]
  end

  actions do
    defaults [:create, :read, :update, :destroy]
  end

  code_interface do
    define_for App.Records
    define :create
    define :read
    define :update
    define :destroy
  end

  postgres do
    table "test_resources"
    repo App.Repo
  end
end

Best, C.

checking the code you changed…

        relationships do
          belongs_to :version_source, unquote(module) do
            destination_attribute(unquote(destination_attribute))
            allow_nil?(false)
            attribute_writable?(true)
            source_attribute(:version_source_id) # your change...
          end

… shouldn’t there be a attribute_type(first_pkey_attr_type) within the belongs_to definition to use the correct type for the related resource as well ?

This would configure that attribute:

          unless unquote(is_nil(first_pkey_attr)) do
             attribute :version_source_id, unquote(Macro.escape(first_pkey_attr_type)) do
               constraints unquote(Macro.escape(first_pkey_attr_constraints))
               allow_nil? false
             end
           end

I’m surprised you have the same issue…is there a different stack trace?

@rgraff may have an idea. As far as I can tell, the problem centers around incorrect constraints for that attribute. However, it could also be something that uuid_attribute is doing strange, I’m not familiar with the inner workings of it.

yes it’s exactly the same stack trace. but I can try searching in the direction of uuid_attribute’s behavior, maybe I can find out something in this corner…

Thanks anyway :pray:

I’m pretty sure Zach’s on the right track. Since I’m not familiar with AshUUID, so this might take some trial and error.

If I declare the pk as explicitly non-prefixed: uuid_attribute :id, prefixed?: false then I finally got my versioning working! :slight_smile:

but yes, this is just a workaround for now…

:thinking: that is definitely strange. I won’t have time to dig into this, but somewhere in this code:

is where that error message is coming from. You could potentially clone down that repo and debug manually to see what the value being provided is.

Hi @zachdaniel

I created a PR with a fix for this issue: fix: correctly carry over first primary key attribute type and constraints by hwuethrich · Pull Request #36 · ash-project/ash_paper_trail · GitHub

The reason why your change did not fix the issue was that you were using the attributes variable, which does not contain the PK in most cases:

2 Likes

wonderful, thank you :slight_smile: I’ve merged your PR.

1 Like