ruby-on-rails 如何预加载has_one_attached variant_record的blob?

5n0oy7gb  于 2023-01-18  发布在  Ruby
关注(0)|答案(1)|浏览(131)

我正在使用Rails www.example.com和ActiveStorage。7.0.3.1 with ActiveStorage.
我有一个

class Element < ApplicationRecord
  has_one_attached :image do |blob|
    blob.variant :large, { resize_to_fill: [744, 387], saver: { quality: 70 } }
    blob.variant :medium, { resize_to_fill: [558, 290], saver: { quality: 70 } }
    blob.variant :small, { resize_to_fill: [372, 194], saver: { quality: 70 } }
  end
end

在我的模板中,我想使用srcset属性以不同的分辨率渲染一个picture标签,如下所示(使用haml):

.element__image-wrapper
  %picture
    = image_tag @element.image.variant(:large).processed.url, width: 744, height: 387, |
      srcset: "#{@element.image.variant(:large).processed.url} 744w, |
      #{@element.image.variant(:medium).processed.url} 558w, |
      #{@element.image.variant(:small).processed.url} 372w"

这可以正常工作,但是如果没有N +1个数据库查询,我就无法完成此操作
我可以这样做:

> element = Element.first
  Element Load
=> #<Element:0x00007fde115ee038
...
> element.image.variant_records.load
  ActiveStorage::Attachment Load
  ActiveStorage::Blob Load
  ActiveStorage::VariantRecord Load
=> [#<ActiveStorage::VariantRecord:0x00007fddf2c30ff0 id: 1, blob_id: 1, variation_digest: "fayCsCJnE0tYtxSs06wT4zzkL9M=">,                                                    
...
> element.image.variant_records.loaded?
=> true
> element.image.variant(:large).processed?
=> true
> element.image.variant(:large).image.blob
  ActiveStorage::Attachment Load
  ActiveStorage::Blob Load
=> #<ActiveStorage::Blob:0x00007fddf31d1270
...

如何预加载variant_recordsimage_attachment: :blob
我已经试过了

> element.reload
  Element Load
=> #<Element:0x00007fde115ee038
> element.image.variant_records.preload(image_attachment: :blob)
  ActiveStorage::Attachment Load
  ActiveStorage::Blob Load
  ActiveStorage::VariantRecord Load
  ActiveStorage::Attachment Load
  ActiveStorage::Blob Load
=> [#<ActiveStorage::VariantRecord:0x00007fddf2c30ff0 id: 1, blob_id: 1, variation_digest: "fayCsCJnE0tYtxSs06wT4zzkL9M=">,

这看起来很有效(第4个和第5个查询是正确的),但是当我访问变体时,它又被加载了:

> element.image.variant_records.loaded?
=> false
> element.image.variant(:large).processed?
  ActiveStorage::VariantRecord Load
=> true
> element.image.variant(:large).image.blob
  ActiveStorage::VariantRecord Load
  ActiveStorage::Attachment Load
  ActiveStorage::Blob Load
=> #<ActiveStorage::Blob:0x00007fde100c2650

是否有可能通过5次查询获得所需的所有数据?

vkc1a9a2

vkc1a9a21#

您可以使用includes预加载blob变体:
例如,对于MyModel模型中的has_many_attached :photos,您

MyModel.includes(photos_attachments: [blob: [variant_records: {image_attachment: :blob}]])

相关问题