Ecto: insert item with assoc (details in body)

This seems like an easy query (and it is) but my Google fu is completely failing me for some reason.

I have a model tag and a model post and I need to create a post, with a tag. Tag <-> Post is a many_to_many assoc, so I cannot just set tag_id to post for example

  student = %Student{}
  |> Student.changeset(attrs)
  |> Ecto.Changeset.put_assoc(:class_lists, [class_list])
  |> Repo.insert()

This does not work, because of a class_list_pkey error - assumedly since Repo.insert tries to insert the class_list as well. However, I cannot just use Repo.update, because I do need to insert the student. What’s the idiomatic way to do this in Ecto?

Right now I’m just running a transaction. Is this really the intended way? I imagine I’m just missing something.

Please note:

“This function should be used when working with the entire association at once (and not a single element of a many-style association) and using data internal to the application.”

This is the ecto documentation example:

tags = Repo.all(from t in Tag, where: in ^params["tags"])

|> Repo.preload(:tags)
|> Ecto.Changeset.cast(params) # No need to allow :tags as we put them directly
|> Ecto.Changeset.put_assoc(:tags, tags) # Explicitly set the tags

As you can see, the example works with the entire User association and preloads the tags assosiated to it. So you have a user with tags.

In the other hand you have a new tags list which are associated with to the user in the put_assoc function.

In your situation, you must first load the class_list similar to the example.

hope this helps.

Best regards