Skip to content

Commit

Permalink
fix: correctly carry over first primary key attribute type and constr…
Browse files Browse the repository at this point in the history
…aints (#36)

The main problem in 7e825a1 was using the `attributes` variable to detect the PK (which only contains attrs from `attributes_as_attributes`).

This commit also fixes an issue on the generated `:has_many` relationsip when the resource is using a PK other than `:id`.
  • Loading branch information
hwuethrich authored Feb 6, 2024
1 parent 7e825a1 commit 6d5cb7c
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 17 deletions.
20 changes: 5 additions & 15 deletions lib/resource/transformers/create_version_resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,10 @@ defmodule AshPaperTrail.Resource.Transformers.CreateVersionResource do

mixin = AshPaperTrail.Resource.Info.mixin(dsl_state) || AshPaperTrail.EmptyUse

first_pkey_attr = Enum.find(attributes, & &1.primary_key?)

first_pkey_attr_type =
first_pkey_attr && first_pkey_attr.type

first_pkey_attr_constraints =
first_pkey_attr && first_pkey_attr.constraints

destination_attribute =
case Ash.Resource.Info.primary_key(dsl_state) do
[key] ->
key
Ash.Resource.Info.attribute(dsl_state, key)

keys ->
raise Spark.Error.DslError,
Expand Down Expand Up @@ -171,11 +163,9 @@ defmodule AshPaperTrail.Resource.Transformers.CreateVersionResource do
end
end

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
attribute :version_source_id, unquote(Macro.escape(destination_attribute.type)) do
constraints unquote(Macro.escape(destination_attribute.constraints))
allow_nil? false
end

attribute :changes, :map do
Expand All @@ -192,7 +182,7 @@ defmodule AshPaperTrail.Resource.Transformers.CreateVersionResource do

relationships do
belongs_to :version_source, unquote(module) do
destination_attribute(unquote(destination_attribute))
destination_attribute(unquote(destination_attribute.name))
allow_nil?(false)
attribute_writable?(true)
source_attribute(:version_source_id)
Expand Down
17 changes: 15 additions & 2 deletions lib/resource/transformers/relate_version_resource.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ defmodule AshPaperTrail.Resource.Transformers.RelateVersionResource do

# sobelow_skip ["DOS.StringToAtom"]
def transform(dsl_state) do
with {:ok, relationship} <-
with {:ok, source_attribute} <- validate_source_attribute(dsl_state),
{:ok, relationship} <-
Transformer.build_entity(Ash.Resource.Dsl, [:relationships], :has_many,
name: :paper_trail_versions,
destination: AshPaperTrail.Resource.Info.version_resource(dsl_state),
destination_attribute: :version_source_id
destination_attribute: :version_source_id,
source_attribute: source_attribute
) do
{:ok,
Transformer.add_entity(dsl_state, [:relationships], %{
Expand All @@ -23,4 +25,15 @@ defmodule AshPaperTrail.Resource.Transformers.RelateVersionResource do
def before?(_), do: false

def after?(_), do: true

defp validate_source_attribute(dsl_state) do
case Ash.Resource.Info.primary_key(dsl_state) do
[key] ->
{:ok, key}

keys ->
{:error,
"Only resources with a single primary key are currently supported. Got keys #{inspect(keys)}"}
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
defmodule AshPaperTrail.Resource.Transformers.CreateVersionResourceTest do
use ExUnit.Case

defmodule Tag do
use Ash.Resource,
data_layer: Ash.DataLayer.Ets,
extensions: [AshPaperTrail.Resource],
validate_api_inclusion?: false

ets do
private? true
end

attributes do
attribute :name, :string do
allow_nil? false
primary_key? true
constraints max_length: 20
end
end
end

defmodule Api do
use Ash.Api, extensions: [AshPaperTrail.Api], validate_config_inclusion?: false

resources do
resource Tag
resource Tag.Version
end
end

describe "attribute :version_source_id" do
setup do
version_source_id = Ash.Resource.Info.attribute(Tag.Version, :version_source_id)
[version_source_id: version_source_id]
end

test "uses resource primary key type", %{version_source_id: version_source_id} do
assert version_source_id.type == Ash.Type.String
end

test "uses resource primary key constraints", %{version_source_id: version_source_id} do
assert version_source_id.constraints == [allow_empty?: false, trim?: true, max_length: 20]
end
end
end

0 comments on commit 6d5cb7c

Please sign in to comment.