Skip to content

polymorphic_on_delete option needs refining and potentially movingΒ #189

Open
@mindok

Description

@mindok

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions