如何 eager_load 附件:1+N 问题不适用于 ActiveStorage 附件
How to eager_load attachments: 1+N problem not working with ActiveStorage attachments
我有一个产品列表,它被序列化为 JSON API 响应
为此,我还需要来自 ActiveStorage
个附件的 imageUrl。
我偶然发现了 1+N 问题。
如您所见,我已经尝试包含任何类型的“includes
”
我已经添加了'with_attached_photos
'
如何解决这个 1+N 问题?
model
:
class Product
ActiveStorage::Current.host = ENV['APPLICATION_URL']
include Rails.application.routes.url_helpers
has_many_attached :photos
has_and_belongs_to :categories
def photo_thumbnail_urls
photos.map do |photo|
# this generates urls for the API
rails_representation_url(photo.variant(thumb_options), host: ActiveStorage::Current.host)
end
end
end
这是我的 controller
:
class ProductsController < ApplicationController
# as you can see, I already tried to include any kind of 'includes'
# and I already added the 'with_attached_photos'
top_rated_products = Product.includes(:categories,
:active_storage_blobs,
:categories_products,
:active_storage_attachments,
photos_attachments: :blob,
where("lower(name) LIKE lower(?)", "%" + query_param + "%").
where("categories_products.category_id": [1,2,3,4]).
with_attached_photos
render json: top_rated_products, each_serializer: TopProductSerializer
结束
这是我的 Serializer
class TopProductSerializer < ActiveModel::Serializer
attribute :id
attribute :name
attribute :photo_thumbnail_urls, key: :images
end
但是我的控制台充满了这样的查询:
Product Load (4.2ms) SELECT "products".* FROM "products" WHERE (lower(name) LIKE lower('%ha%')) ORDER BY created_at asc LIMIT [["LIMIT", 5]]
↳ app/controllers/products_controller.rb:116:in `top_rated'
HABTM_Categories Load (0.3ms) SELECT "categories_products".* FROM "categories_products" WHERE "categories_products"."product_id" IN (, , , , ) [[nil, 740], [nil, 741], [nil, 742], [nil, 744], [nil, 746]]
↳ app/controllers/products_controller.rb:116:in `top_rated'
Category Load (0.2ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" IN (, ) [[nil, 100], [nil, 5107]]
↳ app/controllers/products_controller.rb:116:in `top_rated'
[active_model_serializers] ActiveStorage::Attachment Load (0.2ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = AND "active_storage_attachments"."record_type" = AND "active_storage_attachments"."name" = [["record_id", 740], ["record_type", "Product"], ["name", "photos"]]
[active_model_serializers] ↳ app/models/product.rb:53:in `photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3840], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3841], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3842], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3843], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3844], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
# and so on and so on...
#......
#....
#...
#..
#.
我还错过了什么?
我使用它:
class Product
scope :eager_load_photos, -> { includes photos_attachments: :blob }
end
Product.eager_load_photos.where(......).limit(n) # and so on
1+N 问题现在完全解决了
我有一个产品列表,它被序列化为 JSON API 响应
为此,我还需要来自 ActiveStorage
个附件的 imageUrl。
我偶然发现了 1+N 问题。
如您所见,我已经尝试包含任何类型的“includes
”
我已经添加了'with_attached_photos
'
如何解决这个 1+N 问题?
model
:
class Product
ActiveStorage::Current.host = ENV['APPLICATION_URL']
include Rails.application.routes.url_helpers
has_many_attached :photos
has_and_belongs_to :categories
def photo_thumbnail_urls
photos.map do |photo|
# this generates urls for the API
rails_representation_url(photo.variant(thumb_options), host: ActiveStorage::Current.host)
end
end
end
这是我的 controller
:
class ProductsController < ApplicationController
# as you can see, I already tried to include any kind of 'includes'
# and I already added the 'with_attached_photos'
top_rated_products = Product.includes(:categories,
:active_storage_blobs,
:categories_products,
:active_storage_attachments,
photos_attachments: :blob,
where("lower(name) LIKE lower(?)", "%" + query_param + "%").
where("categories_products.category_id": [1,2,3,4]).
with_attached_photos
render json: top_rated_products, each_serializer: TopProductSerializer
结束
这是我的 Serializer
class TopProductSerializer < ActiveModel::Serializer
attribute :id
attribute :name
attribute :photo_thumbnail_urls, key: :images
end
但是我的控制台充满了这样的查询:
Product Load (4.2ms) SELECT "products".* FROM "products" WHERE (lower(name) LIKE lower('%ha%')) ORDER BY created_at asc LIMIT [["LIMIT", 5]]
↳ app/controllers/products_controller.rb:116:in `top_rated'
HABTM_Categories Load (0.3ms) SELECT "categories_products".* FROM "categories_products" WHERE "categories_products"."product_id" IN (, , , , ) [[nil, 740], [nil, 741], [nil, 742], [nil, 744], [nil, 746]]
↳ app/controllers/products_controller.rb:116:in `top_rated'
Category Load (0.2ms) SELECT "categories".* FROM "categories" WHERE "categories"."id" IN (, ) [[nil, 100], [nil, 5107]]
↳ app/controllers/products_controller.rb:116:in `top_rated'
[active_model_serializers] ActiveStorage::Attachment Load (0.2ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = AND "active_storage_attachments"."record_type" = AND "active_storage_attachments"."name" = [["record_id", 740], ["record_type", "Product"], ["name", "photos"]]
[active_model_serializers] ↳ app/models/product.rb:53:in `photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3840], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3841], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3842], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3843], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
[active_model_serializers] ActiveStorage::Blob Load (0.2ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = LIMIT [["id", 3844], ["LIMIT", 1]]
[active_model_serializers] ↳ app/models/product.rb:55:in `block in photo_thumbnail_urls'
# and so on and so on...
#......
#....
#...
#..
#.
我还错过了什么?
我使用它:
class Product
scope :eager_load_photos, -> { includes photos_attachments: :blob }
end
Product.eager_load_photos.where(......).limit(n) # and so on
1+N 问题现在完全解决了