Description
Describe the bug
The references
config block containing a polymorphic_on_delete :delete
setting is on the "unexpected" side of the relationship between a resource and a polymorphic resource. If it is set on the polymorphic resource side, the generated migration does not implement the delete in the foreign key constraint.
Discussion here
https://elixirforum.com/t/how-to-combine-polymorphic-with-references-on-delete/60756
To Reproduce
defmodule MyApp.Location do
use Ash.Resource, data_layer: AshPostgres.DataLayer
postgres do
repo MyApp.Repo
polymorphic? true
# HAS NO EFFECT
references do
polymorphic_on_delete :delete
end
end
attributes do
uuid_primary_key :id
attribute :resource_id, :uuid do
allow_nil? false
private? true
end
attribute :x, :float
attribute :y, :float
end
end
defmodule MyApp.Event do
use Ash.Resource, data_layer: AshPostgres.DataLayer
postgres do
repo MyApp.Repo
table "events"
# WORKS IF IT IS HERE
references do
polymorphic_on_delete :delete
end
end
attributes do
uuid_primary_key :id
attribute :when, :utc_datetime, allow_nil?: false, default: &DateTime.utc_now/0
attribute :what, :string
attribute :who, :string
end
relationships do
has_one :location, Location do
relationship_context %{data_layer: %{table: "event_locations"}}
destination_attribute :resource_id
end
end
Expected behavior
To be agreed. Currently the config location is surprising as for other relationships it is the "owned" resource that defines the on_delete
behaviour rather than the owning resource. However, where you have multiple relationships to polymorphic resources (to be expected!) and want to control the delete behaviour for each separately it may make sense to do it this way round. So there's a philosophical question to answer first - should the delete behaviour belong to the polymorphic resource or to the relationship? If it is the relationship it should probably be defined at the specific relationship level.
In the example above, this may be something like:
defmodule MyApp.Event do
use Ash.Resource, data_layer: AshPostgres.DataLayer
postgres do
repo MyApp.Repo
table "events"
references do
# Either something here that points to the Location resource, but looks different to
# the existing config for relationships as it is inverted...
end
end
attributes do
uuid_primary_key :id
attribute :when, :utc_datetime, allow_nil?: false, default: &DateTime.utc_now/0
attribute :what, :string
attribute :who, :string
end
relationships do
has_one :location, Location do
# Or probably better here to collect together all the implementation details of the relationship in one place
relationship_context %{data_layer: %{table: "event_locations"}, on_delete: :delete}
destination_attribute :resource_id
end
end
**Runtime
- Elixir version: 1.15.4
- Erlang version: Erlang/OTP 26 [erts-14.0.2]
- OS: Mac
- Ash version: 2.17.17
- Ash Postgres: 1.3.61
- any related extension versions