渴望加载,具体取决于Ruby on Rails中的关联类型

Stu*_*ssa 12 ruby-on-rails polymorphic-associations rails-activerecord

我有一个多态关联(belongs_to :resource, polymorphic: true),其中resource可以有各种不同的模型.为简化问题,假设它可以是a Order或a 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 -%>
Run Code Online (Sandbox Code Playgroud)

目前我的预装用途:

@issues.preload(:resource)
Run Code Online (Sandbox Code Playgroud)

但是我仍然看到加载条件关联的n加一个问题:

SELECT "addresses".* WHERE "addresses"."order_id" = ...
SELECT "locations".* WHERE "locations"."customer_id" = ...
...
Run Code Online (Sandbox Code Playgroud)

有什么好办法解决这个问题?是否可以手动预加载关联?

Mic*_*iak 9

你可以在ActiveRecord::Associations::Preloader课堂的帮助下做到这一点.这是代码:

@issues = Issue.all # Or whatever query
ActiveRecord::Associations::Preloader.new.preload(@issues.select { |i| i.resource_type == "Order" }, { resource: :address })
ActiveRecord::Associations::Preloader.new.preload(@issues.select { |i| i.resource_type == "Customer" }, { resource: :location })
Run Code Online (Sandbox Code Playgroud)

过滤集合时可以使用不同的方法.例如,在我正在使用的项目中group_by

groups = sale_items.group_by(&:item_type)
groups.each do |type, items|
  conditions = case type
  when "Product" then :item
  when "Service" then { item: { service: [:group] } }
end

ActiveRecord::Associations::Preloader.new.preload(items, conditions)
Run Code Online (Sandbox Code Playgroud)

您可以轻松地将此代码包装在某个帮助程序类中,并在应用程序的不同部分中使用它.