diff --git a/server/lib/orcasite/radio/audio_image.ex b/server/lib/orcasite/radio/audio_image.ex index 417c2dc0..96e52d54 100644 --- a/server/lib/orcasite/radio/audio_image.ex +++ b/server/lib/orcasite/radio/audio_image.ex @@ -79,6 +79,9 @@ defmodule Orcasite.Radio.AudioImage do defaults [:read, :destroy, create: :*, update: :*] create :for_feed_segment do + upsert? true + upsert_identity :unique_audio_image + argument :feed_segment_id, :string, allow_nil?: false argument :image_type, Orcasite.Types.ImageType do diff --git a/server/lib/orcasite/radio/audio_image_feed_segment.ex b/server/lib/orcasite/radio/audio_image_feed_segment.ex index 2e1fbacb..f99c4a60 100644 --- a/server/lib/orcasite/radio/audio_image_feed_segment.ex +++ b/server/lib/orcasite/radio/audio_image_feed_segment.ex @@ -15,6 +15,10 @@ defmodule Orcasite.Radio.AudioImageFeedSegment do end end + identities do + identity :unique_audio_image, [:feed_segment_id, :audio_image_id] + end + attributes do uuid_primary_key :id @@ -27,7 +31,14 @@ defmodule Orcasite.Radio.AudioImageFeedSegment do end actions do - defaults [:read, :destroy, create: :*, update: :*] + defaults [:read, :destroy, update: :*] + + create :create do + primary? true + accept :* + upsert? true + upsert_identity :unique_audio_image + end end graphql do diff --git a/server/lib/orcasite/radio/feed.ex b/server/lib/orcasite/radio/feed.ex index cd4bb739..dab2b348 100644 --- a/server/lib/orcasite/radio/feed.ex +++ b/server/lib/orcasite/radio/feed.ex @@ -204,6 +204,7 @@ defmodule Orcasite.Radio.Feed do change |> Ash.Changeset.manage_relationship(:audio_images, audio_image_inputs, + on_lookup: :ignore, on_no_match: {:create, :for_feed_segment}, on_match: :ignore ) diff --git a/server/priv/repo/migrations/20240910222932_update_audio_image_feed_segment_join_table_unique.exs b/server/priv/repo/migrations/20240910222932_update_audio_image_feed_segment_join_table_unique.exs new file mode 100644 index 00000000..64e97c7a --- /dev/null +++ b/server/priv/repo/migrations/20240910222932_update_audio_image_feed_segment_join_table_unique.exs @@ -0,0 +1,21 @@ +defmodule Orcasite.Repo.Migrations.UpdateAudioImageFeedSegmentJoinTableUnique do + @moduledoc """ + Updates resources based on their most recent snapshots. + + This file was autogenerated with `mix ash_postgres.generate_migrations` + """ + + use Ecto.Migration + + def up do + create unique_index(:audio_image_feed_segments, [:feed_segment_id, :audio_image_id], + name: "audio_image_feed_segments_unique_audio_image_index" + ) + end + + def down do + drop_if_exists unique_index(:audio_image_feed_segments, [:feed_segment_id, :audio_image_id], + name: "audio_image_feed_segments_unique_audio_image_index" + ) + end +end diff --git a/server/priv/resource_snapshots/repo/audio_image_feed_segments/20240910222932.json b/server/priv/resource_snapshots/repo/audio_image_feed_segments/20240910222932.json new file mode 100644 index 00000000..6e3025b6 --- /dev/null +++ b/server/priv/resource_snapshots/repo/audio_image_feed_segments/20240910222932.json @@ -0,0 +1,171 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "inserted_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "updated_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "audio_image_feed_segments_feed_segment_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": null, + "table": "feed_segments" + }, + "size": null, + "source": "feed_segment_id", + "type": "uuid" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "audio_image_feed_segments_audio_image_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": null, + "table": "audio_images" + }, + "size": null, + "source": "audio_image_id", + "type": "uuid" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [ + { + "all_tenants?": false, + "concurrently": false, + "error_fields": [ + "feed_segment_id" + ], + "fields": [ + { + "type": "atom", + "value": "feed_segment_id" + } + ], + "include": null, + "message": null, + "name": null, + "nulls_distinct": true, + "prefix": null, + "table": null, + "unique": false, + "using": null, + "where": null + }, + { + "all_tenants?": false, + "concurrently": false, + "error_fields": [ + "audio_image_id" + ], + "fields": [ + { + "type": "atom", + "value": "audio_image_id" + } + ], + "include": null, + "message": null, + "name": null, + "nulls_distinct": true, + "prefix": null, + "table": null, + "unique": false, + "using": null, + "where": null + } + ], + "custom_statements": [], + "has_create_action": true, + "hash": "D8A1FF82B91190958A59F7146B9D440787938C57346C22CB8B90BF3DF6A76D5A", + "identities": [ + { + "all_tenants?": false, + "base_filter": null, + "index_name": "audio_image_feed_segments_unique_audio_image_index", + "keys": [ + { + "type": "atom", + "value": "feed_segment_id" + }, + { + "type": "atom", + "value": "audio_image_id" + } + ], + "name": "unique_audio_image", + "nils_distinct?": true, + "where": null + } + ], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.Orcasite.Repo", + "schema": null, + "table": "audio_image_feed_segments" +} \ No newline at end of file