From b32c2081235d6a3c0f94cc4eb3c026b917ee1e4b Mon Sep 17 00:00:00 2001 From: Ikraam Ghoor Date: Fri, 26 Jun 2026 07:40:05 +0200 Subject: [PATCH] Eager load variant stock on the products API index The products API index rendered each variant's stock on hand without eager loading stock items, so the query count grew with the number of variants across the listed products. Eager loading stock items for the master, the variants, and the variants including master keeps the stock queries constant regardless of how many products and variants are listed. --- api/app/controllers/spree/api/products_controller.rb | 6 ++++-- api/spec/requests/spree/api/products_spec.rb | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/api/app/controllers/spree/api/products_controller.rb b/api/app/controllers/spree/api/products_controller.rb index 5477a14015..859eab17e6 100644 --- a/api/app/controllers/spree/api/products_controller.rb +++ b/api/app/controllers/spree/api/products_controller.rb @@ -9,10 +9,12 @@ def index @products = product_scope.where(id: ids) else products_includes = [ - :variants, :option_types, :product_properties, - {classifications: :taxon} + {classifications: :taxon}, + {master: {stock_items: :stock_location}}, + {variants: {stock_items: :stock_location}}, + {variants_including_master: {stock_items: :stock_location}} ] @products = product_scope .ransack(params[:q]) diff --git a/api/spec/requests/spree/api/products_spec.rb b/api/spec/requests/spree/api/products_spec.rb index 8396e5db19..82eb922245 100644 --- a/api/spec/requests/spree/api/products_spec.rb +++ b/api/spec/requests/spree/api/products_spec.rb @@ -58,6 +58,13 @@ module Spree::Api expect(json_response["per_page"]).to eq(Kaminari.config.default_per_page) end + it "loads stock for every product variant without an N+1" do + 2.times { create(:variant, product: create(:product)) } + + expect { get spree.api_products_path } + .to make_database_queries(matching: /from .spree_stock_items./i, count: 3) + end + it "retrieves a list of products by id" do get spree.api_products_path, params: {ids: [product.id]} expect(json_response["products"].first).to have_attributes(show_attributes)