我有一个包含这两种方法的模型project_lead
和project_operative_lead
。
当我尝试获取这两个属性时,我得到了大量的查询。即使我试图使用包含。
这是我的模特:
class Project < ActiveRecord::Base
has_many :project_sales_contributions, dependent: :destroy
has_many :sales_contributors, through: :project_sales_contributions, source: 'employee'
has_many :project_contributions, dependent: :destroy
has_many :contributors, through: :project_contributions, source: 'employee'
accepts_nested_attributes_for :project_customer_contacts,
:project_contributions,
:project_sales_contributions,
allow_destroy: true,
reject_if: :all_blank
def project_lead
project_contributions.where(role: 'lead').map { |e| e.employee.name }
end
def project_operative_lead
project_contributions.where(role: 'operative_lead').map { |e| e.employee.name }
end
end
这是我的包含声明:
Project.includes(:customer, project_contributions: [ :employee ]).all
但是我仍然会收到n + 1个查询。
有什么方法可以减少查询次数吗?
答案 0 :(得分:6)
where
子句作用于ActiveRecord
对象。 project_contributions
是Enumerable
,因此您可以对其进行迭代方法,例如map
,select
等。无需再次查询该表以获得所需内容。
顺便说一下为什么不在这里使用joins
呢?您可以使用joins
代替include
。使用includes
时,您急切地加载了customer
模型,因为您没有使用Customer
模型的属性,因此您的情况有点过分。只是我的两分钱。
Project.joins(:customer, project_contributions: [ :employee ]).all
答案 1 :(得分:0)
您再次查询project_contributions以打破包含,您可以尝试选择:
project_contributions.select{ |e| e.role == 'lead' }.map{ |e| e.employee.name }