Rails - 关联上的Eager Load Association

Dav*_*ave 2 activerecord ruby-on-rails associations eager-loading

编辑 - 使用'includes'生成SQL'IN'子句.使用Oracle时,这有1000项限制.它不适用于我的公司.还有其他解决方案吗?

是否可以在关联上急切加载关联?

例如,假设我有一个学院课程,一个学院有很多学生.每个学生都属于student_level

class Academy < ActiveRecord::Base
  has_many :students
end

class Student < ActiveRecord::Base
  belongs_to :academy
  belongs_to :student_level
end

class StudentLevel < ActiveRecord::Base
  has_many :students
end
Run Code Online (Sandbox Code Playgroud)

是否有可能在学院中定制关联,以便在我加载学生时,我总是在学生中加载student_level?

换句话说,我希望以下代码段总共产生一个或两个查询,而不是每个学生一个查询:

@academy.students.each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end
Run Code Online (Sandbox Code Playgroud)

我知道如果我将学生从一个协会改为一个方法,我可以做到这一点,但我不想这样做,因为我无法在其他查询中将学生作为一个关联引用.我也知道我可以通过以下方式在SQL中执行此操作,但我想知道是否有一种方法可以在我的关联上没有finder_sql时执行此操作,因为现在我需要在我的默认范围更改时更新我的​​finder_sql,这赢了不加载关联:

SELECT students.*, student_levels.* FROM students
LEFT JOIN student_levels ON students.student_level_id = student_levels.id
WHERE students.academy_id = ACADEMY_ID_HERE
Run Code Online (Sandbox Code Playgroud)

hou*_*se9 5

您是否尝试过使用includes来加载数据?

class Academy < ActiveRecord::Base
  has_many :students

  # you can probably come up with better method name
  def students_with_levels
    # not sure if includes works off associations, see alternate below if it does not
    self.students.includes(:student_level)
  end

  def alternate
    Student.where("academy_id = ?", self.id).includes(:student_level)
  end
end
Run Code Online (Sandbox Code Playgroud)

另见:http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

应该导致3个查询

  • 学院的初步发现
  • 查询Student对象的集合
  • 所有这些Student StudentLevel对象的查询

加法:

# the same can be done outside of methods
@academy.students.includes(:student_level).each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end

Student.where("academy_id = ?", @academy.id).includes(:student_level).each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end
Run Code Online (Sandbox Code Playgroud)

ActiveRelation查询也是可链接的

@academy.students_with_levels.where("name ILIKE ?", "Smi%").each do # ...
Run Code Online (Sandbox Code Playgroud)

关于封装ActiveRecord查询(方法)的一篇相关文章 - http://ablogaboutcode.com/2012/03/22/respect-the-active-record/