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.”
https://hexdocs.pm/ecto/Ecto.Changeset.html#put_assoc/3
This is the ecto documentation example:
tags = Repo.all(from t in Tag, where: t.name in ^params["tags"])
user
|> 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
3 Likes