diff --git a/lib/polymorphic_embed.ex b/lib/polymorphic_embed.ex index 433cc8c..7e64891 100644 --- a/lib/polymorphic_embed.ex +++ b/lib/polymorphic_embed.ex @@ -262,6 +262,8 @@ defmodule PolymorphicEmbed do type_field: type_field } = field_options + list_data_for_field = Map.fetch!(changeset.data, field) + embeds = Enum.map(list_params, fn params -> case do_get_polymorphic_module_from_map(params, type_field, types_metadata) do @@ -275,8 +277,18 @@ defmodule PolymorphicEmbed do :ignore module -> - embed_changeset = changeset_fun.(struct(module), params) - embed_changeset = %{embed_changeset | action: :insert} + data_for_field = + Enum.find(list_data_for_field, fn datum -> + datum.id != nil and datum.id == params[:id] and datum.__struct__ == module + end) + + embed_changeset = + if data_for_field do + %{changeset_fun.(data_for_field, params) | action: :update} + else + %{changeset_fun.(struct(module), params) | action: :insert} + end + maybe_apply_changes(embed_changeset) end end) diff --git a/test/polymorphic_embed_test.exs b/test/polymorphic_embed_test.exs index 4a5c490..d658271 100644 --- a/test/polymorphic_embed_test.exs +++ b/test/polymorphic_embed_test.exs @@ -1260,6 +1260,32 @@ defmodule PolymorphicEmbedTest do assert Enum.at(reminder.contexts, 0).id != Enum.at(updated_reminder.contexts, 0).id assert Enum.at(reminder.contexts, 1).id != Enum.at(updated_reminder.contexts, 1).id + + # Assert that we have same ids when the provided context element has an id + attrs = %{ + contexts: [ + %{ + __type__: "device", + id: Enum.at(reminder.contexts, 0).id, + ref: "12345", + type: "cellphone", + address: "address" + }, + %{ + __type__: "age", + age: "aquarius", + address: "address" + } + ] + } + + updated_reminder = + reminder + |> reminder_module.changeset(attrs) + |> Repo.update!() + + assert Enum.at(reminder.contexts, 0).id == Enum.at(updated_reminder.contexts, 0).id + assert Enum.at(reminder.contexts, 1).id != Enum.at(updated_reminder.contexts, 1).id end end