【问题标题】:has_one without belongs_to in ecto/phoenix/elixirhas_one 在ecto/phoenix/elixir 中没有belongs_to
【发布时间】:2015-09-19 15:49:50
【问题描述】:

问题

我有一个files 表,还有许多其他表可以创建一对一关联,例如users 可能有 avatarposts 可能有 photo

一个可能的解决方案

一个可能的解决方案是创建users_filesposts_files 表并使用has_one :through。但是,这看起来有些过分了。

理想的解决方案

理想的解决方案是定义这样的表

users
 - avatar_id

posts
 - photo_id

并且在has_one 中有with: 参数,所以架构看起来像这样

schema "users" do
    has_one :avatar, MyApp.FileDb, with: :avatar_id, foreign_key: :id #id is default

end

schema "posts" do
    has_one :photo, MyApp.FileDb, with: :photo_id, foreign_key: :id

end

这样您就不需要在files 上定义belongs_to。是否已经有类似的机制? Phoenix 中处理此问题的标准方法是什么?

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    您无法摆脱没有belongs_to,因为这是定义外键的地方。你有两种选择:

    1. 翻转关系,使用户和帖子都有指向文件表的 avatar_id 和 photo_id

    2. 在没有“files”表的情况下定义“users_files”和“posts_files”表。 “users_files”和“posts_files”将具有完整的表结构,可以在 Ecto 的模型级别共享。我们实际上在 Ecto 文档中讨论了这个案例:http://hexdocs.pm/ecto/Ecto.Schema.html#belongs_to/3(参见多态部分)

    【讨论】:

    【解决方案2】:

    我相信这里描述的是单向一对一关联。 files 表可用作头像、发布照片和许多其他内容的基表。如果您将files 表设为“拥有”方,那么您最终会为每个具有文件关联的实体拥有一个 FK 列。

    不幸的是,我相信如果您将 FK 放在头像上(通过使用belongs_to),那么您无法级联删除文件(这是为has_one 保留的)。因此,如果您删除头像,该文件现在是孤立的。理想情况下,头像不仅是关联的所有者(具有 FK),而且还具有级联删除的能力。

    无论如何,如果您不想将 FK 放在文件表上,那么您可以通过删除文件(而不是头像)来解决文件级联问题。它完成了工作,但感觉有点老套(主要是因为你说头像“属于”一个文件,而从域的角度来看,它实际上是相反的)。

    例如,您可以创建一个删除函数来实际删除文件,而不是使用Repo.delete(avatar)。在该功能中,您可以预加载文件,然后将其删除。这将级联删除头像(假设您在文件架构中有has_one,这不会影响数据库)。

    例如:

    def delete(%__MODULE__{} = avatar) do
      avatar
      |> Repo.preload([:file])
      |> Map.get(:file)
      |> Repo.delete()
      |> case do
        {:ok, _file} -> {:ok, avatar}
        {:error, changeset} -> {:error, changeset}
      end
    end
    

    值得注意的是,Doctrine 使用 mappedByinversedBy 等术语来避免这些 ORM/域命名冲突。诚然,这在 Ecto 中很少出现问题,我认为这可能更像是一个例外。

    【讨论】:

      猜你喜欢
      • 2017-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多