Ecto put_assoc/4 - how to remove the association between two existing structures

Hello !

This is the situation:

The Group has an assosiation with Student, many_to_many

So, when I want to remove the association between two existing structures, I do this:

# student_id is the struct that I want to remove from the association with group.
new_students = Enum.filter(group.students, fn student -> student.id !== student_id end)

    group
    |> Ecto.Changeset.change()
    |> Ecto.Changeset.put_assoc(:students, new_students)
    |> Repo.update!()

This is the best practise ? because I feel unconfortable looping over all the associations.

There is a better way ?

Thanks!

Why don’t you just delete the record in the junction table. You got the IDs.

1 Like

Could you remove the Group ID from the student:

student
|> Ecto.Changeset.change(%{group_id: nil})

I agree looping over all associations does not feel like the best approach.

From the docs:

when you find yourself wanting to work only with a subset of the data, then using put_assoc/4 is most likely unnecessary

1 Like

To add on to this answer, I think if he does just this it would violate foreign key constraint.

He could just set it up to nilify though, something like this:

Why would he violate a foreign key constraint? OP has a junction table, let’s say “groups_students”, and removing an association of “groups” and “students” is as simple as deleting a record in the junction table.

P.S. Set to nilify if you don’t care about data integrity.

Ah yes you’re absolutely right, a mistake on my end!

1 Like