【发布时间】:2017-03-13 21:00:28
【问题描述】:
我有一个多态关联 (belongs_to :resource, polymorphic: true),其中 resource 可以是各种不同的模型。为了简化问题,假设它可以是Order 或Customer。
如果是Order,我想预加载订单,并预加载Address。如果是客户,我想预加载Customer 并预加载Location。
使用这些关联的代码执行以下操作:
<%- @issues.each do |issue| -%>
<%- case issue.resource -%>
<%- when Customer -%>
<%= issue.resource.name %> <%= issue.resource.location.name %>
<%- when Order -%>
<%= issue.resource.number %> <%= issue.resource.address.details %>
<%- end -%>
目前我的预加载使用:
@issues.preload(:resource)
但是我仍然看到加载条件关联的 n 加一问题:
SELECT "addresses".* WHERE "addresses"."order_id" = ...
SELECT "locations".* WHERE "locations"."customer_id" = ...
...
有什么好的方法可以解决这个问题?是否可以手动预加载关联?
【问题讨论】:
-
由于您面临的问题等原因,我不再使用多态关联。 (它们还使数据完整性变得更加困难)。
-
Rails 非常智能。你试过
@issues.preloads(resouce: [:location, :address])吗? -
@MarcRohloff 它引发了一个异常
ActiveRecord::AssociationNotFoundError。看起来这行不通(尽管这样的语法是理想的)。 -
@WizardofOgz 我想你获得并失去了一些完整性。使用单独的列,您可能会遇到没有设置任何列的情况 - 或者设置了所有列 - 或者设置了一些列。也就是说 - 它确实使设置外键约束更容易......
-
@stussa 您可以(并且应该)添加数据库约束以仅允许设置一列。这是我的开发团队使用的约束示例。它确保设置了一组 FK 中的一个
CONSTRAINT owner_mutex_required CHECK (1 = (license_id IS NOT NULL)::integer + (contract_id IS NOT NULL)::integer + (policy_id IS NOT NULL)::integer)
标签: ruby-on-rails rails-activerecord polymorphic-associations