Reputation: 2684
My blog app has a feature that allows people to make copies of other people's posts, and host them as their own.
Post
s are associated with owners.
schema "posts" do
field :title, :string
field :content, :string
belongs_to :owner, MyApp.Accounts.User, foreign_key: :owner_id
end
I would like to get a copy of a Post
by id, remove the id and owner_id fields, cast the new owner id, and then insert.
resolve fn (%{post_id: post_id, new_owner_id: new_owner_id}, _info) ->
Repo.get!(Post, post_id)
|> Map.delete(:id)
|> Map.delete(:owner_id)
|> Post.changeset(%{owner_id: new_owner_id})
|> Repo.insert!
end
But when I do, I get this error:
Request: POST /api
** (exit) an exception was raised:
** (RuntimeError) attempting to cast or change association `owner` from `MyApp.Content.List` that was not loaded. Please preload your associations before manipulating them through changesets
What is the correct way to do this copy?
Upvotes: 0
Views: 489
Reputation: 121010
As it was clearly mentioned in the error message:
Please preload your associations before manipulating them through changesets
resolve fn (%{post_id: post_id, new_owner_id: new_owner_id}, _info) ->
Post
|> Repo.preload(:owner) # ⇐ this
|> Repo.get!(post_id)
|> Map.delete(:id)
|> Map.delete(:owner_id)
|> Post.changeset(%{owner_id: new_owner_id})
|> Repo.insert!
end
Sidenote: I believe, you are doing it wrong. The better design would be to reflect the possible future changes in the “cited” post. Instead of copying it’s content, I would rather introduce the new many-to-many relationship between users and posts, called e.g. “copies.”
Copy by reference is better than copy by value. DRY principle is the one of very few that work always.
Upvotes: 1