Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8f9a560
test: Add test template to migration_generator_test.exs for moving po…
arstamm Oct 24, 2026
3892239
test: create the test, "Legacy polymorphic_on_delete generates the ex…
arstamm Oct 25, 2026
a150782
Merge branch 'main' of github.com:arstamm/ash_postgres into 189-enhan…
arstamm Oct 27, 2026
5dad7b6
test: Add legacy polymorphic_on_update test
arstamm Oct 27, 2026
c8aa1a5
test: add legacy polymorphic_name test.
arstamm Oct 27, 2026
a4248a0
fix: Make polymorphic_name usable in the references macro.
arstamm Oct 27, 2026
1f3e53b
test: Add polymorphic depreciation warning tests
arstamm Oct 27, 2026
3a86214
enhansment: Add depreciation warnings to polumorphic commands in refe…
arstamm Oct 27, 2026
8e9fc86
test: Update depreciation tests to check for replacement description.
arstamm Oct 27, 2026
2d08e42
test: Add tests for rejecting multiple legacy configurations to the s…
arstamm Oct 29, 2026
35af5ee
test: on_delete within relationship_context generates the expected fo…
arstamm Oct 29, 2026
b5c47d0
Enhancement: Update polymorpic_on_delete to accomodate both old and n…
arstamm Oct 29, 2026
781a5dd
Enhancement: Implement polymorphic_on_delete and polymorphic_name for…
arstamm Oct 29, 2026
f2f8fe6
test: Tests for new 'on_update' and 'name' options in the relationshi…
arstamm Oct 29, 2026
61cb541
test: "Multiple on_delete configurations within relationship_context …
arstamm Oct 29, 2026
8cf4c8a
test: "Multiple on_update and multiple name configurations within rel…
arstamm Oct 29, 2026
8f4e2bf
test: Using both legacy and new configuration for configuring polymor…
arstamm Oct 29, 2026
87525e9
test: Conflicting polymorphic_on_delete configurations across resourc…
arstamm Oct 29, 2026
efadc1c
test: Refine polymorphic_on_update and polymorphic_name handling to r…
arstamm Oct 30, 2026
80ff16c
test: Omitting both polymorphic_on_delete and on_delete in relationsh…
arstamm Oct 30, 2026
bf30470
test: Omitting resource settings retains default behavior.
arstamm Oct 30, 2026
63dfb79
test: Update comments for separating test sections.
arstamm Oct 30, 2026
b7d5c80
test: Extract helper function from new test.
arstamm Nov 3, 2026
8b29375
test: Create generate_resource_migration helper function.
arstamm Nov 3, 2026
7647b97
test: Apply helpers to the rest of the new tests.
arstamm Nov 3, 2026
339c3fc
test: Macro for test set 1.
arstamm Nov 3, 2026
9821988
test: Apply macros to depreciation warning tests.
arstamm Nov 3, 2026
7ec2f31
test: apply macros to duplicate legacy configuration tests.
arstamm Nov 3, 2026
886dff5
test: apply macros to multi configuration rejection test.
arstamm Nov 3, 2026
85810a9
tests: Create macros for conflicting configurations.
arstamm Nov 3, 2026
58ad9c2
Test: Finish updating tests with macros.
arstamm Nov 4, 2026
4b3783e
test: Correct function names
arstamm Nov 4, 2026
13b3497
test: Update default test with true pre-exsisting default for name.
arstamm Nov 4, 2026
d0eaced
test: Update default test.
arstamm Nov 4, 2026
cef6604
test: Re update default test
arstamm Nov 4, 2026
dbd964a
test: Refactor tests to consolidate common logic.
arstamm Nov 4, 2026
85f8ee2
tests: Update comments
arstamm Nov 5, 2026
7b5c6d7
test: Refactor Legacy tests to use macros.
arstamm Nov 6, 2026
413de1d
Merge branch 'main' of github.com:arstamm/ash_postgres into 189-enhan…
arstamm Nov 6, 2026
4315805
fix: Add documentation for polymorphic name and add polymorphic name …
arstamm Nov 6, 2026
4ed262c
fix: Update data_layer.ex with more depreciation documentation.
arstamm Nov 8, 2026
210ca3a
fix: Update deprecation descriptions.
arstamm Nov 8, 2026
6cef26a
fix: Update DSL-AshPostgres.DataLayer.md with deprecation notices.
arstamm Nov 8, 2026
db094b6
fix: Add deprecation warning in data_layer.ex.
arstamm Nov 8, 2026
b19f5a0
fix: Move deprecation descriptions to correct locations.
arstamm Nov 8, 2026
ec73af6
documentation: add 'Polymorphic references' section in documentation/…
arstamm Nov 10, 2026
23ecbff
documentation: add 'Polymorphic references' documentation.
arstamm Nov 10, 2026
b1128d0
documentation: Move 'Polymorphic references' section to a better loca…
arstamm Nov 10, 2026
9b5c59b
fix: Remove polymorphic_on_delete from label.ex.
arstamm Nov 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ spark_locals_without_parens = [
on_update: 1,
on_update_message: 1,
polymorphic?: 1,
polymorphic_name: 1,
polymorphic_on_delete: 1,
polymorphic_on_update: 1,
prefix: 1,
Expand Down
11 changes: 9 additions & 2 deletions documentation/dsls/DSL-AshPostgres.DataLayer.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ A section for configuring the references (foreign keys) in resource migrations.
This section is only relevant if you are using the migration generator with this resource.
Otherwise, it has no effect.

> ### Deprecated polymorphic options {: .warning}
>
> `polymorphic_on_delete`, `polymorphic_on_update`, and `polymorphic_name` are
> deprecated but remain supported. Use the relationship context described in
> [Polymorphic references](./../topics/resources/polymorphic-resources.md#polymorphic-references) instead.


### Nested DSLs
* [reference](#postgres-references-reference)
Expand All @@ -281,8 +287,9 @@ end

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`polymorphic_on_delete`](#postgres-references-polymorphic_on_delete){: #postgres-references-polymorphic_on_delete } | `:delete \| :nilify \| :nothing \| :restrict \| {:nilify, atom \| list(atom)}` | | For polymorphic resources, configures the on_delete behavior of the automatically generated foreign keys to source tables. |
| [`polymorphic_on_update`](#postgres-references-polymorphic_on_update){: #postgres-references-polymorphic_on_update } | `:update \| :nilify \| :nothing \| :restrict` | | For polymorphic resources, configures the on_update behavior of the automatically generated foreign keys to source tables. |
| [`polymorphic_on_delete`](#postgres-references-polymorphic_on_delete){: #postgres-references-polymorphic_on_delete } | `:delete \| :nilify \| :nothing \| :restrict \| {:nilify, atom \| list(atom)}` | | For polymorphic resources, configures the `on_delete` behavior of the automatically generated foreign keys to source tables. This option is deprecated; use `relationship_context: %{data_layer: %{references: %{on_delete: ...}}}` on the relationship instead. |
| [`polymorphic_on_update`](#postgres-references-polymorphic_on_update){: #postgres-references-polymorphic_on_update } | `:update \| :nilify \| :nothing \| :restrict` | | For polymorphic resources, configures the `on_update` behavior of the automatically generated foreign keys to source tables. This option is deprecated; use `relationship_context: %{data_layer: %{references: %{on_update: ...}}}` on the relationship instead. |
| [`polymorphic_name`](#postgres-references-polymorphic_name){: #postgres-references-polymorphic_name } | `String.t` | | For polymorphic resources, configures the name of the generated foreign-key constraint to the source table. This option is deprecated; use `relationship_context: %{data_layer: %{references: %{name: ...}}}` on the relationship instead. |



Expand Down
37 changes: 37 additions & 0 deletions documentation/topics/resources/polymorphic-resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,40 @@ all resources that are related to it, that set the `%{data_layer: %{table: "tabl
For each of those, a migration is generated/managed automatically. This means that adding reactions
to a new resource is as easy as adding the relationship and table context, and then running
`mix ash.codegen`.

## Polymorphic references

For each `has_many` or `has_one` relationship from a source resource to a polymorphic resource that supplies a table context, AshPostgres generates a foreign key that points to the source resource’s table. This foreign key is created in the `table` specified by the relationship’s `data_layer` context.

To configure the foreign key, add a `references` map alongside `table` in the relationship’s `data_layer` context:

```elixir
relationships do
has_many :event_locations, MyApp.EventLocation,
relationship_context: %{
data_layer: %{
table: "event_locations",
references: %{
on_delete: :delete,
on_update: :update,
name: "event_locations_event_id_fkey"
}
}
},
destination_attribute: :event_id
end
```

### Options

The following options go inside `relationship_context.data_layer.references`:

| Name | Type | Default | Docs |
|------|------|---------|------|
| `on_delete` | `:delete \| :nilify \| :nothing \| :restrict \| {:nilify, atom \| list(atom)}` | `:nothing` | Configures what happens when a source-table row is deleted. |
| `on_update` | `:update \| :nilify \| :nothing \| :restrict` | `:nothing` | Configures what happens when the referenced column in the source table is updated. |
| `name` | `String.t` | generated | Sets the name of the generated foreign-key constraint. |

The legacy `polymorphic_on_delete`, `polymorphic_on_update`, and `polymorphic_name` options are deprecated but remain supported for backwards compatibility. New configurations should use `relationship_context.data_layer.references`. See the [DSL reference](../../dsls/DSL-AshPostgres.DataLayer.md#postgres-references) for the legacy options.

Remove the corresponding legacy option when moving a setting into the relationship context. Configuring both forms for the same setting raises an error, even when their values match.
25 changes: 22 additions & 3 deletions lib/data_layer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ defmodule AshPostgres.DataLayer do
polymorphic_name: [
type: :string,
doc:
"For polymorphic resources, then index name to use for the foreign key to the source table."
"For polymorphic resources, configures the name of the foreign-key constraint to the source table."
]
]
}
Expand Down Expand Up @@ -238,11 +238,25 @@ defmodule AshPostgres.DataLayer do

@references %Spark.Dsl.Section{
name: :references,
deprecations: [
polymorphic_on_delete:
"Use `relationship_context: %{data_layer: %{references: %{on_delete: ...}}}` on the relationship instead.",
polymorphic_on_update:
"Use `relationship_context: %{data_layer: %{references: %{on_update: ...}}}` on the relationship instead.",
polymorphic_name:
"Use `relationship_context: %{data_layer: %{references: %{name: ...}}}` on the relationship instead."
],
describe: """
A section for configuring the references (foreign keys) in resource migrations.

This section is only relevant if you are using the migration generator with this resource.
Otherwise, it has no effect.

> ### Deprecated polymorphic options {: .warning}
>
> `polymorphic_on_delete`, `polymorphic_on_update`, and `polymorphic_name` are
> deprecated but remain supported. Use the relationship context described in
> [Polymorphic references](./../topics/resources/polymorphic-resources.md#polymorphic-references) instead.
""",
examples: [
"""
Expand All @@ -261,12 +275,17 @@ defmodule AshPostgres.DataLayer do
{:tagged_tuple, :nilify, {:wrap_list, :atom}}
]},
doc:
"For polymorphic resources, configures the on_delete behavior of the automatically generated foreign keys to source tables."
"For polymorphic resources, configures the `on_delete` behavior of the automatically generated foreign keys to source tables. This option is deprecated; use `relationship_context: %{data_layer: %{references: %{on_delete: ...}}}` on the relationship instead."
],
polymorphic_on_update: [
type: {:one_of, [:update, :nilify, :nothing, :restrict]},
doc:
"For polymorphic resources, configures the on_update behavior of the automatically generated foreign keys to source tables."
"For polymorphic resources, configures the `on_update` behavior of the automatically generated foreign keys to source tables. This option is deprecated; use `relationship_context: %{data_layer: %{references: %{on_update: ...}}}` on the relationship instead."
],
polymorphic_name: [
type: :string,
doc:
"For polymorphic resources, configures the name of the generated foreign-key constraint to the source table. This option is deprecated; use `relationship_context: %{data_layer: %{references: %{name: ...}}}` on the relationship instead."
]
]
}
Expand Down
47 changes: 42 additions & 5 deletions lib/migration_generator/migration_generator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3837,12 +3837,10 @@ defmodule AshPostgres.MigrationGenerator do
multitenancy: multitenancy(relationship.source),
table: AshPostgres.DataLayer.Info.table(relationship.source),
schema: AshPostgres.DataLayer.Info.schema(relationship.source),
on_delete: AshPostgres.DataLayer.Info.polymorphic_on_delete(relationship.source),
on_update: AshPostgres.DataLayer.Info.polymorphic_on_update(relationship.source),
on_delete: polymorphic_on_delete(relationship),
on_update: polymorphic_on_update(relationship),
primary_key?: source_attribute.primary_key?,
name:
AshPostgres.DataLayer.Info.polymorphic_name(relationship.source) ||
"#{relationship.context[:data_layer][:table]}_#{destination_attribute_source}_fkey"
name: polymorphic_name(relationship, destination_attribute_source)
})
else
attribute
Expand All @@ -3855,6 +3853,45 @@ defmodule AshPostgres.MigrationGenerator do
end
end

defp polymorphic_on_delete(relationship) do
relationship_context_on_delete =
get_in(relationship.context, [:data_layer, :references, :on_delete])

legacy_on_delete = AshPostgres.DataLayer.Info.polymorphic_on_delete(relationship.source)

if relationship_context_on_delete && legacy_on_delete do
raise "Conflicting configurations for references: both relationship_context references on_delete and polymorphic_on_delete are configured"
end

relationship_context_on_delete || legacy_on_delete
end

defp polymorphic_on_update(relationship) do
relationship_context_on_update =
get_in(relationship.context, [:data_layer, :references, :on_update])

legacy_on_update = AshPostgres.DataLayer.Info.polymorphic_on_update(relationship.source)

if relationship_context_on_update && legacy_on_update do
raise "Conflicting configurations for references: both relationship_context references on_update and polymorphic_on_update are configured"
end

relationship_context_on_update || legacy_on_update
end

defp polymorphic_name(relationship, destination_attribute_source) do
relationship_context_name = get_in(relationship.context, [:data_layer, :references, :name])

legacy_name = AshPostgres.DataLayer.Info.polymorphic_name(relationship.source)

if relationship_context_name && legacy_name do
raise "Conflicting configurations for references: both relationship_context references name and polymorphic_name are configured"
end

relationship_context_name || legacy_name ||
"#{relationship.context[:data_layer][:table]}_#{destination_attribute_source}_fkey"
end

defp do_snapshot(resource, table, schema \\ nil) do
%{
attributes: attributes(resource, table),
Expand Down
Loading
Loading