Rails急于在索引上加载自定义has_many

时间:2018-05-03 17:33:59

标签: ruby-on-rails ruby ruby-on-rails-3 eager-loading

Ruby 2.1,Rails 3.2
我的项目模型中有这种关系

scope :active, -> { where( deleted_at: nil ) }
has_many :foremen, class_name: "ProjectsUser",  conditions: ['current_foreman = 1']

在控制器中:

@projects = Project.includes(:foremen).active

生成此SQL

ProjectsUser Load (3.3ms)  SELECT `projects_users`.* FROM `projects_users` WHERE `projects_users`.`project_id` IN (122, 130, ...etc.) AND ( current_foreman = 1)

但是当我在视图中调用关系时......

<% @projects.each do |project| %>
  <%= project.foremen.current_foreman %>
<% end %> 

每次都会运行另一个SQL查询。

ProjectsUser Load (2.5ms)  SELECT `projects_users`.* FROM `projects_users` WHERE `projects_users`.`project_id` = 122 AND (current_foreman = 1 )
ProjectsUser Load (2.5ms)  SELECT `projects_users`.* FROM `projects_users` WHERE `projects_users`.`project_id` = 130 AND (current_foreman = 1 )
ProjectsUser Load (2.5ms)  SELECT `projects_users`.* FROM `projects_users` WHERE `projects_users`.`project_id` = 151 AND (current_foreman = 1 )
etc...
我是误会了吗?不应该加载这些记录吗?
我该怎么写这个,所以它只运行ProjectsUser的一个查询?

2 个答案:

答案 0 :(得分:0)

我认为这是正常的,你在项目循环中调用它。

答案 1 :(得分:0)

所以我做了一些挖掘,发现我的逻辑是正确的;这不会自己生成任何其他查询。问题是我正在调用该对象的方法。

以下内容不会调用任何查询:

 project.current_foremen_and_managers.select{|f| f.current_foreman}.sort_by{ |f| f.added_at}.first

但是,当您将额外的逻辑移动到关联类中的方法时,它会生成更多的sql

class ProjectUser < ActiveRecord::Base
  def self.find_first_foreman
    select{|f| f.current_foreman}.sort_by{ |f| f.added_at}.first
  end
end

然后,如果我调用此方法,则运行查询

project.current_foremen_and_managers.find_first_foreman

我不完全确定为什么会发生这种情况,如果有人有解释我很乐意听到。