【问题标题】:Rails - Eager Load Association on an AssociationRails - 关联上的急切负载关联
【发布时间】:2013-05-10 19:05:25
【问题描述】:

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

是否可以在关联上预先加载关联?

例如,假设我有一个学院课程,一个学院有很多学生。每个学生都属于_to 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

是否可以在 Academy 中定制关联,以便在我加载学生时,我总是将 student_level 与学生一起加载?

换句话说,我希望以下代码部分产生一到两个查询,而不是为每个学生生成一个查询:

@academy.students.each do |student|
  puts "#{student.name} - #{student.student_level.level_name}"
end

我知道如果我将学生从关联更改为方法,我可以这样做,但我不想这样做,因为我无法在其他查询中引用学生作为关联。我也知道我可以通过以下方式在 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

【问题讨论】:

  • 老问题,但关于编辑中提到的.includes() 生成的IN-clause:类方法.eager_load() 可用于生成左外连接而不是in-clause:@ 987654321@
  • 感谢更新

标签: ruby-on-rails activerecord associations eager-loading


【解决方案1】:

您是否尝试过使用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

另请参阅:http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

应该会产生 3 个查询

  • 学院的初步发现
  • 对学生对象集合的查询
  • 所有学生 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

ActiveRelation 查询也可以链接

@academy.students_with_levels.where("name ILIKE ?", "Smi%").each do # ...

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

【讨论】:

  • 在我最初的问题中:“我知道如果我将学生从关联更改为方法,我可以做到这一点,但我不想这样做,因为我无法参考学生作为我其他查询中的关联。”也许这是唯一的方法。
  • 添加了“添加”部分,您不仅可以使用 activerecord 方法中的包含技术
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多