ruby-on-rails – ActiveRecord渴望加载多个belongs_to关联
发布时间:2020-12-16 19:14:26 所属栏目:百科 来源:网络整理
导读:问题 我有以下ActiveRecord模型: class Person belongs_to :favourite_car,class_name: 'Car' belongs_to :business_car,class_name: 'Car' belongs_to :home_car,class_name: 'Car'end 当我想访问所有这三个关联时,它会生成三个选择查询: SELECT * FROM c
问题
我有以下ActiveRecord模型: class Person belongs_to :favourite_car,class_name: 'Car' belongs_to :business_car,class_name: 'Car' belongs_to :home_car,class_name: 'Car' end 当我想访问所有这三个关联时,它会生成三个选择查询: SELECT * FROM cars WHERE cars.id = ? 这基本上是N 1问题. 理想情况下,我希望它只生成一个表单查询 SELECT * FROM cars WHERE cars.id IN (?,?,?) 可能的方案 我可以把它移到has_many:through => :join_table与连接表中的列关联以指示关联类型是什么,然后使用includes([:join_table,:cars])来急切加载关联.但是,在这种情况下,它只将3个查询减少到2,并引入了一个额外的表. 另一种可能的方法 另一种可能的解决方案是手动加载关联,如下所示: module EagerLoader def eager_load(*associations) reflections = associations.map { |association| self.class.reflections[association.to_sym] } raise 'Not all are valid associations' if reflections.any?(&:nil?) reflections.group_by { |association| association.klass }.each do |klass,reflections| load_associations(klass,reflections) end self end private def load_associations(klass,reflections) primary_key = klass.primary_key ids = reflections.map { |reflection| public_send(reflection.foreign_key) } records = klass.where(id: ids) reflections.each_with_index do |reflection,i| record = records.find do |record| record.public_send(primary_key) == ids[i] end public_send("#{reflection.name}=",record) end end end 我测试了它,它的工作原理. class Person include EagerLoader end Person.find(2).eager_load(:favorite_car,:business_car,:home_car) 但是,当你想要做的事情时,这仍然无法帮助你 Person.includes(:favourite_car,:home_car) 例如,在人员索引页面上.这会将查询数量从3N减少到4,但实际上只需要2个. 有没有更好的解决方案来解决这个问题? 解决方法
关于手动Eager加载有一篇很棒的帖子.
http://mrbrdo.wordpress.com/2013/09/25/manually-preloading-associations-in-rails-using-custom-scopessql/ 我想这就是你一直在寻找的东西: owners = People.all association_name = :photos owners.each do |owner| record = whatever_you_want association = owner.association(association_name) association.target = record association.set_inverse_instance(record) end (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |