app/models/solidus/elastic_product/serializer.rb
# Operates the same as `each` only:
#
# * It operates in batches so if a lot of products need to be uploaded
#   we uses constant memory.
# * Each batch operates in a transaction so the serialization is faster
# * Complicated queries are pre-loaded and monkey-patched into avoid
#   N+1 loading.
# * Related data needed by the SB upload are pre-loaded to avoid N+1 loading
Operates the same as `each` only:
It operates in batches so if a lot of products need to be uploaded
we uses constant memory.
Each batch operates in a transaction so the serialization is faster
Complicated queries are pre-loaded and monkey-patched into avoid
N+1 loading.
Related data needed by the SB upload are pre-loaded to avoid N+1 loading
Operates the same as ` each ` only : It operates in batches so if a lot of products need to be uploaded we uses constant memory . Each batch operates in a transaction so the serialization is faster Complicated queries are pre - loaded and monkey - patched into avoid N + 1 loading . Related data needed by the SB upload are pre - loaded to avoid N + 1 loading
def each_for_serialization &blk
          Spree::Taxon.reset_cache!
          sub_query = select('id').to_sql
          stock_scope = Spree::StockItem.
            joins(:variant).references(:variant).
            where "product_id IN (#{sub_query})"
          products_on_hand = stock_scope.group(:product_id).sum :count_on_hand
          variants_on_hand = stock_scope.
            joins(:stock_location).references(:stock_location).
            where(spree_stock_locations: {active: true}).
            group(:variant_id).sum :count_on_hand
          distinct = ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' ? 'distinct on (product_id) ' : ''
          images = Spree::Image.
            select(distinct + 'spree_variants.product_id, spree_assets.*').
            joins("join spree_variants on viewable_id = spree_variants.id").
            order("spree_variants.product_id", :position, "spree_variants.position", "spree_variants.id").
            where("spree_variants.product_id in (#{sub_query})").
            group_by &:product_id
          popularity = Spree::LineItem.
            joins(:variant).
            where("product_id IN (#{sub_query})").
            group(:product_id).count
          prices = Spree::Price.
            joins(:variant).
            where("spree_variants.product_id in (#{sub_query})").
            group("spree_variants.product_id").
            minimum(:amount)
          preload = -> (object, method, value) { object.singleton_class.send(:define_method, method) { value } }
          scope = includes :elastic_state, :indexable_classifications, :master,
            indexable_product_properties: :property,
            variants: [{ option_values: :option_type }]
          records = scope.to_a 
          State.transaction do
            records.each do |product|
              preload[product, :total_on_hand, products_on_hand[product.id] || 0]
              preload[product.master, :total_on_hand, variants_on_hand[product.master.id] || 0]
              for variant in product.variants
                preload[variant, :total_on_hand, variants_on_hand[variant.id] || 0]
              end
              preload[product, :display_image, images.key?(product.id) && images[product.id][0] || Spree::Image.new]
              preload[product, :indexed_popularity, popularity[product.id] || 0]
              preload[product, :indexed_price, prices[product.id] || 0]
              for classification in product.indexable_classifications
                taxon = Spree::Taxon.by_id[classification.taxon_id]
                preload[classification, :taxon, taxon]
                preload[taxon, :self_and_ancestors, Spree::Taxon.self_and_ancestors(taxon)]
              end
              blk.call product
            end
          end
        end
def each_for_serialization & blk Spree :: Taxon . reset_cache! sub_query = select ( 'id' ) . to_sql stock_scope = Spree :: StockItem . joins ( :variant ) . references ( :variant ) . where "product_id IN (#{sub_query})" products_on_hand = stock_scope . group ( :product_id ) . sum :count_on_hand variants_on_hand = stock_scope . joins ( :stock_location ) . references ( :stock_location ) . where ( spree_stock_locations : { active : true } ) . group ( :variant_id ) . sum :count_on_hand distinct = ActiveRecord :: Base . connection . adapter_name == 'PostgreSQL' ? 'distinct on (product_id) ' : '' images = Spree :: Image . select ( distinct + 'spree_variants.product_id, spree_assets.*' ) . joins ( "join spree_variants on viewable_id = spree_variants.id" ) . order ( "spree_variants.product_id" , :position , "spree_variants.position" , "spree_variants.id" ) . where ( "spree_variants.product_id in (#{sub_query})" ) . group_by & :product_id popularity = Spree :: LineItem . joins ( :variant ) . where ( "product_id IN (#{sub_query})" ) . group ( :product_id ) . count prices = Spree :: Price . joins ( :variant ) . where ( "spree_variants.product_id in (#{sub_query})" ) . group ( "spree_variants.product_id" ) . minimum ( :amount ) preload = -> ( object , method , value ) { object . singleton_class . send ( :define_method , method ) { value } } scope = includes :elastic_state , :indexable_classifications , :master , indexable_product_properties : :property , variants : [ { option_values : :option_type } ] records = scope . to_a State . transaction do records . each do | product | preload [ product , :total_on_hand , products_on_hand [ product . id ] || 0 ] preload [ product . master , :total_on_hand , variants_on_hand [ product . master . id ] || 0 ] for variant in product . variants preload [ variant , :total_on_hand , variants_on_hand [ variant . id ] || 0 ] end preload [ product , :display_image , images . key? ( product . id ) && images [ product . id ] [ 0 ] || Spree :: Image . new ] preload [ product , :indexed_popularity , popularity [ product . id ] || 0 ] preload [ product , :indexed_price , prices [ product . id ] || 0 ] for classification in product . indexable_classifications taxon = Spree :: Taxon . by_id [ classification . taxon_id ] preload [ classification , :taxon , taxon ] preload [ taxon , :self_and_ancestors , Spree :: Taxon . self_and_ancestors ( taxon ) ] end blk . call product end end end
Operates the same as `each` only:
 It operates in batches so if a lot of products need to be uploaded
we uses constant memory.
Operates the same as ` each ` only : It operates in batches so if a lot of products need to be uploaded we uses constant memory .
# Pre-load and monkey-patch data in during loop since it's a non-standard # type of preloading # With postgres, we can grab just the first image per product, saving on memory. # The order bit takes care to select the master images if any first. # Very rought implementation # Load outside of transaction to prevent excessive locking
blk