<commit_before>module Spree
  module Core
    module Search
      class Base
        attr_accessor :properties
        attr_accessor :current_user
        attr_accessor :current_currency

        def initialize(params)
          self.current_currency = Spree::Config[:currency]
          @properties = {}
          prepare(params)
        end

        def retrieve_products
          @products = get_base_scope
          curr_page = page || 1

          unless Spree::Config.show_products_without_price
            @products = @products.where("spree_prices.amount IS NOT NULL").
                                  where("spree_prices.currency" => current_currency)
          end
          @products = @products.page(curr_page).per(per_page)
        end

        def method_missing(name)
          if @properties.has_key? name
            @properties[name]
          else
            super
          end
        end

        protected
          def get_base_scope
            base_scope = Spree::Product.spree_base_scopes.active
            base_scope = base_scope.in_taxon(taxon) unless taxon.blank?
            base_scope = get_products_conditions_for(base_scope, keywords)
            base_scope = add_search_scopes(base_scope)
            base_scope = add_eagerload_scopes(base_scope)
            base_scope
          end

          def add_eagerload_scopes scope
            # TL;DR Switch from `preload` to `includes` as soon as Rails starts honoring
            # `order` clauses on `has_many` associations when a `where` constraint
            # affecting a joined table is present (see
            # https://github.com/rails/rails/issues/6769).
            #
            # Ideally this would use `includes` instead of `preload` calls, leaving it
            # up to Rails whether associated objects should be fetched in one big join
            # or multiple independent queries. However as of Rails 4.1.8 any `order`
            # defined on `has_many` associations are ignored when Rails builds a join
            # query.
            #
            # Would we use `includes` in this particular case, Rails would do
            # separate queries most of the time but opt for a join as soon as any
            # `where` constraints affecting joined tables are added to the search;
            # which is the case as soon as a taxon is added to the base scope.
            scope = scope.preload(master: :prices)
            scope = scope.preload(master: :images) if include_images
            scope
          end

          def add_search_scopes(base_scope)
            search.each do |name, scope_attribute|
              scope_name = name.to_sym
              if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
                base_scope = base_scope.send(scope_name, *scope_attribute)
              else
                base_scope = base_scope.merge(Spree::Product.ransack({scope_name => scope_attribute}).result)
              end
            end if search.is_a?(ActionController::Parameters)
            base_scope
          end

          # method should return new scope based on base_scope
          def get_products_conditions_for(base_scope, query)
            unless query.blank?
              base_scope = base_scope.like_any([:name, :description], query.split)
            end
            base_scope<commit_msg>Preload tax_category to omit N+1 queries<commit_after>module Spree
  module Core
    module Search
      class Base
        attr_accessor :properties
        attr_accessor :current_user
        attr_accessor :current_currency

        def initialize(params)
          self.current_currency = Spree::Config[:currency]
          @properties = {}
          prepare(params)
        end

        def retrieve_products
          @products = get_base_scope
          curr_page = page || 1

          unless Spree::Config.show_products_without_price
            @products = @products.where("spree_prices.amount IS NOT NULL").
                                  where("spree_prices.currency" => current_currency)
          end
          @products = @products.page(curr_page).per(per_page)
        end

        def method_missing(name)
          if @properties.has_key? name
            @properties[name]
          else
            super
          end
        end

        protected
          def get_base_scope
            base_scope = Spree::Product.spree_base_scopes.active
            base_scope = base_scope.in_taxon(taxon) unless taxon.blank?
            base_scope = get_products_conditions_for(base_scope, keywords)
            base_scope = add_search_scopes(base_scope)
            base_scope = add_eagerload_scopes(base_scope)
            base_scope
          end

          def add_eagerload_scopes scope
            # TL;DR Switch from `preload` to `includes` as soon as Rails starts honoring
            # `order` clauses on `has_many` associations when a `where` constraint
            # affecting a joined table is present (see
            # https://github.com/rails/rails/issues/6769).
            #
            # Ideally this would use `includes` instead of `preload` calls, leaving it
            # up to Rails whether associated objects should be fetched in one big join
            # or multiple independent queries. However as of Rails 4.1.8 any `order`
            # defined on `has_many` associations are ignored when Rails builds a join
            # query.
            #
            # Would we use `includes` in this particular case, Rails would do
            # separate queries most of the time but opt for a join as soon as any
            # `where` constraints affecting joined tables are added to the search;
            # which is the case as soon as a taxon is added to the base scope.
            scope = scope.preload(:tax_category)
            scope = scope.preload(master: :prices)
            scope = scope.preload(master: :images) if include_images
            scope
          end

          def add_search_scopes(base_scope)
            search.each do |name, scope_attribute|
              scope_name = name.to_sym
              if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
                base_scope = base_scope.send(scope_name, *scope_attribute)
              else
                base_scope = base_scope.merge(Spree::Product.ransack({scope_name => scope_attribute}).result)
              end
            end if search.is_a?(ActionController::Parameters)
            base_scope
          end

          # method should return new scope based on base_scope
          def get_products_conditions_for(base_scope, query)
            unless query.blank?
              base_scope = base_scope.like_any([:name, :description], query.split)
            end
            base_scope
{'fraction_non_alphanumeric': 0.06440281030444965, 'fraction_numerical': 0.002488290398126464, 'mean_word_length': 1.9351374570446735, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1345704', 'n_tokens_mistral': 1787, 'n_tokens_neox': 1739, 'n_words': 510}