我的博客应用程序有一项功能,允许人们复制其他人的帖子,并将其作为自己的帖子托管。
Post
与所有者相关联。
schema "posts" do
field :title, :string
field :content, :string
belongs_to :owner, MyApp.Accounts.User, foreign_key: :owner_id
end
我想通过ID获取Post
的副本,删除id和owner_id字段,转换新的所有者ID,然后插入。
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
但是当我这样做时,我收到了这个错误:
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
执行此复制的正确方法是什么?
答案 0 :(得分:1)
正如错误消息中明确提到的那样:
请在通过更改集操作之前预先加载您的关联
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
旁注:我相信,你做错了。更好的设计是反映“引用”帖子未来可能发生的变化。我宁愿在用户和帖子之间引入新的多对多关系,而不是复制它的内容。 “拷贝”。
按引用复制比按值复制更好。 DRY principle是少数能够始终的人之一。