<NME> quantifier.rb
<BEF> # frozen_string_literal: true

module Spree
  module Stock

      def initialize(variant)
        @variant = variant
        @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant, Spree::StockLocation.table_name =>{ :active => true})
      end

      def total_on_hand

      def total_on_hand
        # Associated stock_items no longer exist if the variant has been soft-deleted. A variant
        # may still be in an active cart after it's deleted, so this will mark it as out of stock.
        return 0 if @variant.deleted?

        stock_items.sum(:count_on_hand)
      end

      def backorderable?
        stock_items.any?(&:backorderable)
      def can_supply?(required)
        total_on_hand >= required || backorderable?
      end
    end
  end
end
  end
end

<MSG> Modify Spree::Stock::Quantifier to not re-fetch stock items if they are already eager-loaded

This helps to remove a big N+1 here, and will also be very helpful elsewhere in the app

<DFF> @@ -5,7 +5,7 @@ module Spree
 
       def initialize(variant)
         @variant = variant
-        @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant, Spree::StockLocation.table_name =>{ :active => true})
+        @stock_items = fetch_stock_items
       end
 
       def total_on_hand
@@ -23,6 +23,16 @@ module Spree
       def can_supply?(required)
         total_on_hand >= required || backorderable?
       end
+
+      private
+
+      def fetch_stock_items
+        # Don't re-fetch associated stock items from the DB if we've already eager-loaded them
+        return @variant.stock_items.to_a if @variant.stock_items.loaded?
+
+        Spree::StockItem.joins(:stock_location).
+          where(:variant_id => @variant, Spree::StockLocation.table_name => { active: true })
+      end
     end
   end
 end

{'commit': "diff --git a/app/models/spree/stock/quantifier.rb b/app/models/spree/stock/quantifier.rb\nindex 6b1c11de6..806fdf33d 100644\n--- a/app/models/spree/stock/quantifier.rb\n+++ b/app/models/spree/stock/quantifier.rb\n@@ -5,7 +5,7 @@ module Spree\n \n       def initialize(variant)\n         @variant = variant\n-        @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant, Spree::StockLocation.table_name =>{ :active => true})\n+        @stock_items = fetch_stock_items\n       end\n \n       def total_on_hand\n@@ -23,6 +23,16 @@ module Spree\n       def can_supply?(required)\n         total_on_hand >= required || backorderable?\n       end\n+\n+      private\n+\n+      def fetch_stock_items\n+        # Don't re-fetch associated stock items from the DB if we've already eager-loaded them\n+        return @variant.stock_items.to_a if @variant.stock_items.loaded?\n+\n+        Spree::StockItem.joins(:stock_location).\n+          where(:variant_id => @variant, Spree::StockLocation.table_name => { active: true })\n+      end\n     end\n   end\n end\n", 'commit_subject': 'Modify Spree::Stock::Quantifier to not re-fetch stock items if they are already eager-loaded', 'repo_name': 'openfoodfoundation/openfoodnetwork', 'committer': {'name': 'Matt-Yorkley', 'email': '52dd53e39aabc3ad9893bf4bdc49ac9095b2e246@users.noreply.github.com', 'time_sec': '1586416777', 'tz_offset': '120', 'date': {'seconds': '1586416777'}}, 'commit_tree': '31fa482ff2378e1437b5c4d1cb2e89b48e8958c3', 'commit_message': 'Modify Spree::Stock::Quantifier to not re-fetch stock items if they are already eager-loaded\n\nThis helps to remove a big N+1 here, and will also be very helpful elsewhere in the app\n', 'language_name': 'JavaScript', 'license': 'agpl-3.0', 'hunks': "@@ -5,7 +5,7 @@ module Spree\n \n       def initialize(variant)\n         @variant = variant\n-        @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant, Spree::StockLocation.table_name =>{ :active => true})\n+        @stock_items = fetch_stock_items\n       end\n \n       def total_on_hand\n@@ -23,6 +23,16 @@ module Spree\n       def can_supply?(required)\n         total_on_hand >= required || backorderable?\n       end\n+\n+      private\n+\n+      def fetch_stock_items\n+        # Don't re-fetch associated stock items from the DB if we've already eager-loaded them\n+        return @variant.stock_items.to_a if @variant.stock_items.loaded?\n+\n+        Spree::StockItem.joins(:stock_location).\n+          where(:variant_id => @variant, Spree::StockLocation.table_name => { active: true })\n+      end\n     end\n   end\n end\n", 'addition_count': 11, 'deletion_count': 1, 'src_file': 'a/app/models/spree/stock/quantifier.rb', 'tgt_file': 'b/app/models/spree/stock/quantifier.rb', 'file_extension': '.rb', 'before_file': "# frozen_string_literal: true\n\nmodule Spree\n  module Stock\n\n      def initialize(variant)\n        @variant = variant\n        @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant, Spree::StockLocation.table_name =>{ :active => true})\n      end\n\n      def total_on_hand\n\n      def total_on_hand\n        # Associated stock_items no longer exist if the variant has been soft-deleted. A variant\n        # may still be in an active cart after it's deleted, so this will mark it as out of stock.\n        return 0 if @variant.deleted?\n\n        stock_items.sum(:count_on_hand)\n      end\n\n      def backorderable?\n        stock_items.any?(&:backorderable)\n      def can_supply?(required)\n        total_on_hand >= required || backorderable?\n      end\n    end\n  end\nend\n  end\nend\n", 'message': 'Modify Spree::Stock::Quantifier to not re-fetch stock items if they are already eager-loaded\n\nThis helps to remove a big N+1 here, and will also be very helpful elsewhere in the app\n', 'author_name': 'Matt-Yorkley', 'lang': 'rb'}