Skip to content

Commit 2d68876

Browse files
committed
Fixed N+1 loading tax categories during tax calculation
Calculating order taxes read each line item's tax category through its variant and, when the variant had none, through its product. With the associations unloaded that meant two queries per line item, every time taxes were recalculated. Preloading the variant and product for all line items keeps that load constant regardless of how many items the order has.
1 parent 8d781ac commit 2d68876

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

core/app/models/spree/tax_calculator/default.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ def initialize(order)
2323
#
2424
# @return [Spree::Tax::OrderTax] the calculated taxes for the order
2525
def calculate
26+
ActiveRecord::Associations::Preloader.new(records: order.line_items, associations: {variant: :product}).call
27+
2628
Spree::Tax::OrderTax.new(
2729
order_id: order.id,
2830
order_taxes: order_rates,

core/spec/models/spree/tax_calculator/default_spec.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,18 @@
7676
expect(order_tax.label).to eq "Flat Book Fee"
7777
end
7878
end
79+
80+
context "with multiple line items" do
81+
before do
82+
2.times do
83+
order.contents.add(FactoryBot.create(:product, tax_category: books_category).master)
84+
end
85+
order.reload
86+
end
87+
88+
it "loads line item variants in a single query" do
89+
expect { calculator.calculate }.to make_database_queries(matching: /from "spree_variants".*id" IN \(/im, count: 1)
90+
end
91+
end
7992
end
8093
end

0 commit comments

Comments
 (0)