【问题标题】:Eagerload has_one association with a table that has multiple related valuesEagerload has_one 与具有多个相关值的表的关联
【发布时间】:2019-01-20 08:16:23
【问题描述】:

所以我定义了以下模型:

class Album
  has_many :photos
  has_one :cover_photo, class_name: "Photo"
end

class Photo
  belongs_to :photo
end

我现在要做的是在加载这样的专辑时立即加载cover_photo 关联:

Album.where(...).includes(:cover_photo)

但根据 ActiveRecord 文档和观察到的行为,limit(这是 has_one 关联所定义的)不受尊重。所以我得到以下查询:

Photo Load (1.0ms)  SELECT "photos".* FROM "photos" WHERE "photos"."album_id" IN (5, 4, 2, 1)

虽然album.cover_photo 现在返回单个对象而不触发额外查询,但显然所有照片都从数据库中加载,这不是我想要的。

我知道我可以使用 JOIN 来实现这一点,并且可以访问相册对象中的照片属性,但我真的需要能够使用 Photo 模型,因为解释照片属性的知识就在那里.

【问题讨论】:

  • 如果查询有限制,如果您加载多个专辑,它不会破坏预加载吗?假设您有 5 张专辑,每张专辑都有一张封面照片。如果预加载查询有 LIMIT 1,那么最后 4 个专辑将不会加载它们的 cover_photo,因为查询被限制为返回单行(除非它们具有相同的 cover_photo)。
  • @kaspernj 是的,这就是为什么 ActiveRecord 去掉了LIMIT 子句,只从数据库中提取所有照片记录,但通过Album#cover_photo API 只公开其中一个。但这是一种内存浪费

标签: sql ruby-on-rails ruby activerecord


【解决方案1】:

这篇文章准确地回答了我的问题,也回答了我关于如何手动将记录预加载到 AR 关联中的另一个问题 - https://mrbrdo.wordpress.com/2013/09/25/manually-preloading-associations-in-rails-using-custom-scopessql/

帖子中的相关代码:

class Album < ActiveRecord::Base
  has_many :photos
  has_one :display_photo, -> {
    self.select_values = ["DISTINCT ON(photos.album_id) photos.*"]
    order('photos.album_id')
    }, class_name: "Photo"
end

【讨论】:

    猜你喜欢
    • 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
    相关资源
    最近更新 更多