From e24027a8d0ebf8fa3bd43a4e1b832ef43b43e173 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 7 Jan 2016 10:52:36 +1100 Subject: [PATCH] Speed up add to cart: Update the order once per fee calculation, rather than for every line item x fee --- app/models/spree/adjustment_decorator.rb | 14 ++++++++++++ app/models/spree/order_decorator.rb | 28 +++++++++++++++--------- spec/models/spree/order_spec.rb | 6 +++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/app/models/spree/adjustment_decorator.rb b/app/models/spree/adjustment_decorator.rb index fb3b190394..0d1bc941f6 100644 --- a/app/models/spree/adjustment_decorator.rb +++ b/app/models/spree/adjustment_decorator.rb @@ -35,5 +35,19 @@ module Spree def display_included_tax Spree::Money.new(included_tax, { :currency => currency }) end + + def self.without_callbacks + skip_callback :save, :after, :update_adjustable + skip_callback :destroy, :after, :update_adjustable + + result = yield + + ensure + set_callback :save, :after, :update_adjustable + set_callback :destroy, :after, :update_adjustable + + result + end + end end diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 8f1c0381b1..53e80bbdef 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -164,21 +164,29 @@ Spree::Order.class_eval do def update_distribution_charge! with_lock do - EnterpriseFee.clear_all_adjustments_on_order self - line_items.each do |line_item| - if provided_by_order_cycle? line_item - OpenFoodNetwork::EnterpriseFeeCalculator.new.create_line_item_adjustments_for line_item + # Without intervention, the Spree::Adjustment#update_adjustable callback is called + # once for every (line item x fee), which triggers a costly Spree::Order#update! + Spree::Adjustment.without_callbacks do + EnterpriseFee.clear_all_adjustments_on_order self - else - pd = product_distribution_for line_item - pd.create_adjustment_for line_item if pd + line_items.each do |line_item| + if provided_by_order_cycle? line_item + OpenFoodNetwork::EnterpriseFeeCalculator.new.create_line_item_adjustments_for line_item + + else + pd = product_distribution_for line_item + pd.create_adjustment_for line_item if pd + end + end + + if order_cycle + OpenFoodNetwork::EnterpriseFeeCalculator.new.create_order_adjustments_for self end end - if order_cycle - OpenFoodNetwork::EnterpriseFeeCalculator.new.create_order_adjustments_for self - end + # After fees are calculated, we update the order once + update! end end diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index e50a64a4d9..300cf26bac 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -54,6 +54,8 @@ describe Spree::Order do product_distribution.should_receive(:create_adjustment_for).with(line_item) subject.stub(:product_distribution_for) { product_distribution } + subject.should_receive(:update!) + subject.update_distribution_charge! end @@ -65,6 +67,8 @@ describe Spree::Order do subject.stub(:product_distribution_for) { nil } + subject.should_receive(:update!) + subject.update_distribution_charge! end @@ -90,6 +94,8 @@ describe Spree::Order do OpenFoodNetwork::EnterpriseFeeCalculator.any_instance.stub(:create_order_adjustments_for) subject.stub(:order_cycle) { order_cycle } + subject.should_receive(:update!) + subject.update_distribution_charge! end