Ecto/Phoenix 上的多态性与 Rails 上创建的数据库
Polymorphism on Ecto/Phoenix with database created on Rails
我很难尝试在 Ecto 中实现多态性。我的主要问题是我正在尝试处理 Phoenix 中的多态关联,但是数据来自我们使用和创建的数据库——老实说,有点老了——主要应用程序,它基于 Rails。
其他机型都处理的很好,Rails和Phoenix这边读写数据都没有问题。
具有多态性的除外。我花了很多时间阅读 Ecto 的文档,我发现 "rails way" 不是 "right way" 但我有点卡在这里,因为我的模型已经写在 rails 上side(一些主题已经存储了数百万行)。
所以我在 Rails 中有这个抽象模型 element
,它代表 7 tables(图像、视频、excel 等)。我还有另外两个 table,doc_images
和 items
。另外两个 tables belongs_to element
因此具有 rails 魔法场 element_id
和 element_type
。同样,postgres 中不存在 element
table,只有 images
、videos
等
我尝试在 Phoenix 中设置我的 images
和 videos
模型,但是当我将此代码放入我的 items
模式时:
schema "items" do
belongs_to(:video, Video, foreign_key: :element_id)
belongs_to(:image, Image, foreign_key: :element_id)
field(:element_type, :string)
timestamps([{:created_at, :updated_at}])
end
由于 (ArgumentError) field/association :element_id is already set on schema
,我无法编译。
我可以手动执行所有查询,但我似乎无法正确编写模式。
最后,我需要能够使这些类型的查询正常工作(显然,除了 doc/video/image 部分外,所有这些都工作得很好):
MyApp.Repo.one(from t in Token,
join: p in assoc(t, :project),
join: vc in assoc(p, :vcard),
join: th in assoc(p, :theme),
left_join: z in assoc(p, :zip_archive), on: p.id == z.project_id,
join: c in assoc(p, :company),
join: b in assoc(c, :binfos),
left_join: pi in assoc(p, :project_items), on: pi.id == pi.project_id,
left_join: i in assoc(pi, :item),
left_join: d in assoc(i, :doc),
left_join: v in assoc(i, :video),
left_join: im in assoc(i, :image),
left_join: di in assoc(d, :doc_image),
where: t.token_url == ^token_url,
preload: [project: [:vcard, :theme, :zip_archive, [company: :binfos], project_items: [item: [doc: :doc_image, :video, :image]]]])
所以我的问题是:我还有哪些其他选择?我可以将列甚至其他 table 添加到我的数据库(并从其中现有的 table 迁移数据)但我无法从我的 [=53] 中删除 element
逻辑=] 应用程序(主要是为了时间问题,因为我团队中的其他人喜欢 Rails 方式 :p)。
有没有人能够以 Rails 的方式处理 Ecto 中的多态性,如果强烈反对的话?
我不会尝试复制 ruby-on-rails 行为,而是采用最简单、最干净的解决方案。
删除 items
中的任何 belongs_to
。
schema "items" do
field :element_id, :integer
field :element_type, :string
...
end
向 changeset
添加验证,检查具有此 element_id
的相应 element_type
是否存在。
来自 Token
的 Select 加入了一切,除了 doc/image/etc 动物园。
Select 来自 element_type
作者 element_id
。
这肯定会起作用,尽管它意味着每个 select 和 upsert 都有一个额外的查询,但我相信结果代码的清晰度很快就会得到回报。
现在在不加入的情况下进行正常查询
我很难尝试在 Ecto 中实现多态性。我的主要问题是我正在尝试处理 Phoenix 中的多态关联,但是数据来自我们使用和创建的数据库——老实说,有点老了——主要应用程序,它基于 Rails。
其他机型都处理的很好,Rails和Phoenix这边读写数据都没有问题。
具有多态性的除外。我花了很多时间阅读 Ecto 的文档,我发现 "rails way" 不是 "right way" 但我有点卡在这里,因为我的模型已经写在 rails 上side(一些主题已经存储了数百万行)。
所以我在 Rails 中有这个抽象模型 element
,它代表 7 tables(图像、视频、excel 等)。我还有另外两个 table,doc_images
和 items
。另外两个 tables belongs_to element
因此具有 rails 魔法场 element_id
和 element_type
。同样,postgres 中不存在 element
table,只有 images
、videos
等
我尝试在 Phoenix 中设置我的 images
和 videos
模型,但是当我将此代码放入我的 items
模式时:
schema "items" do
belongs_to(:video, Video, foreign_key: :element_id)
belongs_to(:image, Image, foreign_key: :element_id)
field(:element_type, :string)
timestamps([{:created_at, :updated_at}])
end
由于 (ArgumentError) field/association :element_id is already set on schema
,我无法编译。
我可以手动执行所有查询,但我似乎无法正确编写模式。
最后,我需要能够使这些类型的查询正常工作(显然,除了 doc/video/image 部分外,所有这些都工作得很好):
MyApp.Repo.one(from t in Token,
join: p in assoc(t, :project),
join: vc in assoc(p, :vcard),
join: th in assoc(p, :theme),
left_join: z in assoc(p, :zip_archive), on: p.id == z.project_id,
join: c in assoc(p, :company),
join: b in assoc(c, :binfos),
left_join: pi in assoc(p, :project_items), on: pi.id == pi.project_id,
left_join: i in assoc(pi, :item),
left_join: d in assoc(i, :doc),
left_join: v in assoc(i, :video),
left_join: im in assoc(i, :image),
left_join: di in assoc(d, :doc_image),
where: t.token_url == ^token_url,
preload: [project: [:vcard, :theme, :zip_archive, [company: :binfos], project_items: [item: [doc: :doc_image, :video, :image]]]])
所以我的问题是:我还有哪些其他选择?我可以将列甚至其他 table 添加到我的数据库(并从其中现有的 table 迁移数据)但我无法从我的 [=53] 中删除 element
逻辑=] 应用程序(主要是为了时间问题,因为我团队中的其他人喜欢 Rails 方式 :p)。
有没有人能够以 Rails 的方式处理 Ecto 中的多态性,如果强烈反对的话?
我不会尝试复制 ruby-on-rails 行为,而是采用最简单、最干净的解决方案。
删除 items
中的任何 belongs_to
。
schema "items" do
field :element_id, :integer
field :element_type, :string
...
end
向 changeset
添加验证,检查具有此 element_id
的相应 element_type
是否存在。
Token
的 Select 加入了一切,除了 doc/image/etc 动物园。
Select 来自 element_type
作者 element_id
。
这肯定会起作用,尽管它意味着每个 select 和 upsert 都有一个额外的查询,但我相信结果代码的清晰度很快就会得到回报。
现在在不加入的情况下进行正常查询