Rails 5中如何从已实例化ActiveRecord对象预加载多层一对一关联
解决单个User实例一次性加载嵌套关联的问题
嘿,这个场景我太熟悉了!当手里已经有单个User实例,想一次性加载它的child和嵌套的toy,确实不能直接用includes(因为它是针对查询集合的方法)。这里给你几个靠谱的解决方案:
方法一:用ActiveRecord预加载器(推荐)
Rails提供了专门的预加载工具,可以直接给单个实例加载关联,执行一次SQL就能把child和toy的数据都拉回来,还会自动绑定到user的属性上:
ActiveRecord::Associations::Preloader.new.preload(user, child: :toy)
之后你再访问user.child或者user.child.toy,就不会触发额外的数据库查询了,完美解决问题。
方法二:重新查询该用户并预加载关联
如果你的user实例还没有做过修改,或者重新查询成本很低,可以直接重新查一次这个用户,带上嵌套关联的预加载:
user = User.includes(child: :toy).find(user.id)
这行代码会执行一次包含user、child、toy的关联查询,返回的user实例已经把所有需要的数据都加载好了,后续访问关联不会再发SQL。
补充:你之前尝试的方法为什么不生效?
user.child.toy:会先查child(第一次SQL),再查toy(第二次SQL),典型的N+1问题user.includes(child: :toy):includes是ActiveRecord::Relation的方法,单个模型实例没法调用它user.child.includes(:toy):同理,child是单个实例,不是查询集合,不能用includesuser.association(:child).scope.eager_load(:toy).first:确实能生成正确的关联查询,但查询出来的对象没有自动绑定到原user实例的child属性上,你得手动赋值user.child = 查出来的child对象才能生效,不如前两种方法方便
内容的提问来源于stack exchange,提问作者you786
相关产品推荐
相关产品推荐

