Hey,
I have a liveview application with a nested changeset.
There is study on top.
This has a cast_assoc for scenarios.
And scenarios has a cast_assoc for scenario_tasks.
I am having a problem on the scenario tasks level.
When I add a 3rd new scenario_task in liveview I am seeing this warning:
[warning] found duplicate primary keys for association/embed
:scenario_tasks
inScenario
. In case of duplicate IDs, only the last entry with the same ID will be kept. Make sure that all entries in:scenario_tasks
have an ID and the IDs are unique between them
I think this is because now in cast there are multiple scenario_tasks with nil for id.
This seems to not cause any problems for add/update, but when I am deleting these entries either all of them go at once, or the last 2 go at once.
I am also not sure if the interaction with the changeset is correct (legacy code).
Add is done like this:
def handle_add_task(socket, scenario_i) do
{scenario_index, _rem} = Integer.parse(scenario_i)
study_changeset = socket.assigns.study_changeset
scenarios = Ecto.Changeset.get_field(study_changeset, :scenarios, []) || []
nth_scenario = Enum.at(scenarios, scenario_index)
updated_tasks = nth_scenario.scenario_tasks ++ [%{title: ""}]
nth_scenario_with_new_task =
Ecto.Changeset.change(nth_scenario, %{scenario_tasks: updated_tasks})
scenarios_with_i_updated =
List.replace_at(scenarios, scenario_index, nth_scenario_with_new_task)
updated_study_changeset =
Ecto.Changeset.put_change(study_changeset, :scenarios, scenarios_with_i_updated)
{:noreply, assign(socket, study_changeset: updated_study_changeset)}
end
Remove is done like this:
def handle_event("remove_task", %{"task" => task_i, "scenario" => scenario_i}, socket) do
{scenario_index, _rem} = Integer.parse(scenario_i)
{task_index, _rem} = Integer.parse(task_i)
study_changeset = socket.assigns.study_changeset
scenarios = Ecto.Changeset.get_field(study_changeset, :scenarios, []) || []
nth_scenario = Enum.at(scenarios, scenario_index)
scenario_tasks = Ecto.Changeset.get_field(nth_scenario, :scenario_tasks, [])
updated_tasks = List.delete_at(scenario_tasks, task_index)
nth_scenario_changeset = Ecto.Changeset.change(nth_scenario, %{scenario_tasks: updated_tasks})
updated_scenarios = List.replace_at(scenarios, scenario_index, nth_scenario_changeset)
study_changeset = Ecto.Changeset.put_change(study_changeset, :scenarios, updated_scenarios)
{:noreply, assign(socket, study_changeset: study_changeset)}
end
My questions would be, is the handling of the changes to the changeset fine this way?
Any ideas how to handle the duplicate primary keys warning?
Thank you