Put_assoc vs force_change when modifying known associations?

I’m trying to figure out the “best practice” when modifying data within some of my schemas. When working with has_many relationships, I’ve found that it’s easier to work with the child data rather than the parents. As such, there are often times where I want to move child data from one parent to another, or nilify the relationship. The two ways I’ve found of doing this are as follows, and I was wondering if one was considered to be better than the other.

In both cases, we assume the post and comment have already been inserted.
Given a %Post{} that has_many %Comments{}, if you wanted to add a new comment to this post, you could do it from the comments perspective of:

def add_comment(%Post{} = post, %Comment{} = comment) do
    comment
    |> Repo.preload(:post)
    |> Ecto.Changeset.put_assoc(:post, post)
    |> Repo.update!()
end
def alt_add_comment(%Post{} = post, %Comment{} = comment) do
    comment
    |> Ecto.Changeset.change()
    |> Ecto.Changeset.force_change(:post_id, post.id)
    |> Repo.update!()
end

In the second case, we avoid the preload and assign the post id directly to the changeset, without knowing what Post the comment might already be associated with.
Are either of these scenarios considered worse than the other? Is there a reason I should be avoiding one of these?

Also, if I wanted to associate many (existing) comments to a different/new post, is it better to use an Ecto.Multi transaction that changes their post_ids, or is it better to preload the post’s comments, and then append/modify them directly?

I appreciate any discussion or help.

2 Likes