gpt4 book ai didi

ruby-on-rails - 我可以在不实例化相关模型的情况下从一对一关系中急切加载属性以进行委托(delegate)吗?

转载 作者:行者123 更新时间:2023-12-04 06:32:06 25 4
gpt4 key购买 nike

想象一下:

class House < ActiveRecord::Base

belongs_to :ground

delegate :elevation_in_meters, to: :ground

# attributes: stories, roof_type
end

class Ground < ActiveRecord::Base
has_one :house

# attributes: elevation_in_meters, geo_data
end

然后急切加载地面,以便在不加载 Ground 的情况下调用 house.elevation_in_meters 我可以这样做:

houses=House.includes(:ground).first(3)

这个问题是,整个 Ground 对象实际上是用所有属性实例化的,包括 geo_data 属性——在这种情况下我不需要它。我关心的原因是查询需要非常高效,geo_data 是一个非常大的文本字段。我只需要读取委托(delegate)属性,而不是写入它们。

在不从 Ground 加载所有内容的情况下,我可以采用什么方法从 Ground 预先加载 elevation_in_meters 属性?

顺便说一句,我在 Rails 4.1 上

注意:我希望 House 默认具有这种预加载行为,这样我就不需要每次都指定它。

最佳答案

首先为您想要部分获取的模型写一个范围,然后选择您喜欢的字段。请注意,我为选择使用了全名(带有表名)和一个字符串。我不确定您是否可以只选择 select(:elevation_in_meters,:geo_data) 因为我已经从我们的生产示例中复制了它,并且我们使用了一些与此范围的连接,如果没有表名将无法工作.自己试试吧。

class Ground < ActiveRecord::Base
has_one :house

attributes: elevation_in_meters, geo_data
scope :reduced, -> {
select('grounds.elevation_in_meters, grounds.geo_data')
}

end

有了作用域,你可以创建第二个 belongs_to 关系(不要害怕它会弄乱你的第一个关系,因为 Rails 关系基本上只是为你创建的方法),它调用你的 地面模型。

class House < ActiveRecord::Base

belongs_to :ground
belongs_to :ground_reduced, ->(_o) { reduced },
class_name: 'Ground', foreign_key: 'ground_id'

delegate :elevation_in_meters, to: :ground_reduced
# go for an additional delegation if
# you also need this with the full object sometimes

end

最后你可以像这样调用你的查询:

houses = House.includes(:ground_reduced).first(3)

从技术上讲,这不是您问题的正确答案,因为 Ground 对象仍处于实例化状态。但是该实例只会包含您想要的数据,而其他字段将为零,因此它应该可以解决问题。

更新:正如我刚刚看到的,您希望最好将此行为作为默认行为,只需为您的房屋添加一个范围:

scope :reduced, -> { includes(:ground_reduced) }

然后您可以将其添加为您的默认范围,因为您的原始关系不会受此影响。

关于ruby-on-rails - 我可以在不实例化相关模型的情况下从一对一关系中急切加载属性以进行委托(delegate)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31561809/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com