【发布时间】:2017-04-20 20:22:20
【问题描述】:
在向现有模型添加新关联时,我对 Ecto 感到相当困惑。假设我有一些用户可以点赞帖子的讨论板,并且我有以下模型:
schema "discussion_items" do
many_to_many :likes, XXX.Tag, join_through: "discussion_items_likes"
timestamps()
end
schema "likes" do
belongs_to :user, XXX.User
timestamps()
end
现在假设我有一个现有的DiscussionItem,我想为此添加一个类似的关联,这就是我正在尝试的(简化):
user = Repo.one(User)
discussion_item = Repo.one(from d in DiscussionItem, preload [:likes])
like_changeset = Like.changeset(%Like{})
|> Ecto.Changeset.put_assoc(:user, user)
changeset = Ecto.Changeset.change(discussion_item)
|> Ecto.Changeset.put_assoc(:likes, [like_changeset])
Ecto.update!(changeset)
我发现这将在第一次正确创建 Like 和关联,但随后抱怨我需要一些 id 形式的其他信息:
您正在尝试更改关系:喜欢 XXX.DiscussionItem, 但缺少数据
如果您尝试更新现有条目,请确保 您在数据旁边包含条目主键 (ID)。
如果你有很多孩子的关系,至少相同的N 必须在更新时给予孩子。默认情况下是不可能的 孤儿嵌入或关联记录,尝试这样做会导致 此错误消息。
以下是让我感到困惑的事情(有一些):
- 此错误消息似乎表明,为了更新一个关联项目,我需要提供一个包含所有项目的更改集,包括已更改的项目。这看起来很疯狂,所以我猜我看错了。
- 我不想更新点赞关联——我想添加一个。 put_assoc 在这里是不是错误的选择?
- 我真的需要预先加载喜欢才能插入一个项目吗?即使在更新时,我也不想加载整个关联集合来更改一个。
- 是否需要加载
User和Dicussion_item才能在此处添加点赞?
【问题讨论】:
-
似乎我找到了答案,put_assoc 需要所有现有项目加上我要添加的项目本身通过更改集运行。这似乎效率很低,所以希望有更好的方法。
-
您为什么使用
many_to_many来表示喜欢和讨论项目?一次点赞不应该只计算一个讨论项吗? -
我有几件我想要喜欢的东西,讨论项目只是其中之一,所以会有几个连接表。反正真的是跑题了,我真正想知道的是如何在不加载世界的情况下在多对多关系中插入一个新项目,上面的例子不是那么重要
-
this 可能是最好的选择。它有点冗长,但我认为一切变得如此简单是值得的。
-
干杯贾斯汀,很遗憾我必须这样做,但这比替代方案要好得多。
标签: elixir phoenix-framework ecto