多态关联如何与 Ecto 一起工作?

Posted

技术标签:

【中文标题】多态关联如何与 Ecto 一起工作?【英文标题】:How does Polymorphic association work with Ecto? 【发布时间】:2015-05-16 06:17:52 【问题描述】:

当我阅读https://github.com/elixir-lang/ecto/issues/389 及其相关问题时,Ecto 似乎支持多态关联。

假设我需要一个关于任务和事件模型的评论模型关联。如果我对 Ecto 与自定义源关联的理解是正确的,那么我们需要四个表和三个模型,

表格

任务 事件 tasks_cmets events_cmets

型号

任务 事件 评论

任务和事件模型将与自定义源具有 has_many 关联,如下所示。

defmodule ExampleApp.Task do
  use ExampleApp.Web, :model

  schema "tasks" do
    field :title, :string
    field :body, :string
    has_many :comments, "tasks_comments", Comment

    timestamps
  end
end

defmodule ExampleApp.Event do
  use ExampleApp.Web, :model

  schema "events" do
    field :title, :string
    field :body, :string
    has_many :comments, "events_comments", Comment

    timestamps
  end
end

现在我不明白 Comment 模型应该是什么样子?

Comment 模型如何处理两个表?以及它如何处理与不同模型的 belongs_to 关联?

【问题讨论】:

【参考方案1】:

如果你使用上面的设计,评论模型实际上没有任何表,它的表是由关联定义的。因此,要获取所有事件的所有 cmets,您可以这样做:

from c in "events_comments", Comment

在某些情况下这是一项很棒的技术,它允许您不将存储(表)与模型耦合。您可以对不同的表使用相同的模型。

但是,如果您想获取所有 cmets 并将它们与事件和任务相关联,那么您可以使用 through 关系。您将拥有“events”“events_cmets”“cmets”和“tasks”“tasks_cmets”“cmets”。

另一种方法是使用 Rails 进行多态关联的方式,并在 Comment 模型中定义一个“种类”列。它确实会破坏数据库引用,但这是解决此问题的另一种方法。

我会就此事改进 Ecto 文档,感谢您的反馈!

【讨论】:

何塞,感谢您的回答。您的回答引发了多个问题。也许这一切都是微不足道的。 1.“评论模型实际上没有任何表”=>评论模型如何在没有模式的情况下工作。我正在阅读“模式 == 表”。如何在没有模式的情况下验证 Comment,从而没有变更集? 2. 'rails way' 在 Ecto 协会中是如何运作的?有没有示例代码?我没有看到支持此功能的源代码或文档。 1.评论模型没有表格,但通过关联构建时有表格。所以秘诀是使用assoc(task, :comments),而不是%Comment。我在这里记录了这些:github.com/elixir-lang/ecto/commit/… 2. rails 方式在 Ecto 关联中不起作用,因为它通常是不好的做法,因为数据库无法保留其引用。您必须手动构建查询并设置正确的字段。 我还有一些相关的问题,但在提问之前我需要做一些功课。我可能会将其发布在邮件列表上,因为它可能更多的是意见而不是客观答案。谢谢你,何塞。 对于关注这个问题的人,后续帖子在这里:groups.google.com/forum/#!topic/elixir-ecto/mldnA3qx6Ak

以上是关于多态关联如何与 Ecto 一起工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 NSDate 与关联对象一起工作?

Elixir ecto 2 创建 many_to_many 关联

Ecto - 如何通过特定查询获取“has_many”

删除 Ecto 中的关联(多对多)

ecto 变更集为现有添加关联

具有多态实体的子类关联表的 SQLAlchemy 设置