<commit_before>module SimpleSalesforce
  module SalesforceObject # :nodoc:

    module Finders
      
      def self.included(klass)
        klass.class_eval do
          extend ClassMethods
        end
      end
      
      module ClassMethods

        # Queries Salesforce and returns an instantiated object or an array of instantiated objects
        # Syntax find(:first, :conditions => {}), :find(:first, :conditions => ""), find(:all, :conditions => {}), find(:all, :conditions => "")
        def find(*args)
          options = args.extract_options!
          soql_conditions = construct_soql_conditions(options[:conditions])
          limit = options[:limit]
          case args.first
            when :all
              results = query_and_instantiate(:many, soql_conditions, limit)
            when :first
              results = query_and_instantiate(:one, soql_conditions, limit = 1)
            else
              # Find the object by its Salesforce Id and disregard :conditions and :limit
              # dontwork
              soql_conditions = construct_soql_conditions(:salesforce_id => args.first)
              results = query_and_instantiate(:one, soql_conditions, limit = 1)
            end
        end
        
        def method_missing(method_id, value)
          case method_id.to_s
            when /^find_(all_by|by)_([_a-zA-Z]\w*)$/
              finder = $1 == "all_by" ? :all : :first
              var = $2
              find(finder, :conditions => {var.to_sym => value})
            else
              super
          end
        end
        
        def query_and_instantiate(mode, soql_conditions, limit)
          # p construct_query_string(soql_conditions, limit) # debug
          query_response = SimpleSalesforce::Binding.binding.query :queryString => construct_query_string(soql_conditions, limit)
          case mode
          when :many
            instantiate_objects_from_query_response(query_response)
          when :one
            instantiate_single_object_from_query_response(query_response)
          end
        end
        
        # Figures out if the conditions are a single string (e.g. "Contact(FirstName) = 'Joe'") or a hash (e.g. #{:first_name => "Joe"})
        # If it's a hash, build the conditions out to SOQL
        def construct_soql_conditions(conditions = {})
          conditions = {} if conditions.nil?
          if conditions.is_a?(Hash)
            # It's a hash of conditions which we need to format, converting from local fieldnames to Salesforce object fieldnames in the process
            soql_conditions = format_conditions(conditions)
          else
            # It's probably a string, e.g. find(:all, :conditions => "Contact(FirstName) = 'Joe'")
            soql_conditions = [conditions]
          end
          soql_conditions.empty? ? [] : soql_conditions
        end
        
        # Returns an array of SOQL WHERE clause strings, given an array of hashes of the format #{:local_field => "value"}
        # This function interrogates the SalesforceObject Class to find the salesforce field for each local field
        def format_conditions(conditions)
          soql_conditions = []
          conditions.each do |local_field, value|
            salesforce_field = fields.select {|f| f[:field] == local_field.to_sym}.first[:salesforce_field] rescue nil
            soql_conditions << "#{salesforce_field} LIKE '#{value}'" unless salesforce_field.nil?
          end
          soql_conditions
        end

        # Construct SOQL query string from conditions array and limit number
        # The conditions array can be a single string or array of strings and will be joined with 'AND' if necessary
        def construct_query_string(soql_conditions, limit = nil)
          select_soql = "SELECT #{salesforce_fields.join(",")} "
          from_soql = "FROM #{salesforce_object_type}"
          where_soql = "#{' WHERE ' unless soql_conditions.empty?}#{soql_conditions.join(' AND ')}"
          limit_soql = "#{" LIMIT #{limit}" if limit}"
          "#{select_soql}#{from_soql}#{where_soql}#{limit_soql}"
        end
        
        # Return an array of SalesforceObjects of the appropriate class given a RForce response hash
        def instantiate_objects_from_query_response(response)
          records = extract_records_from_response(response)
          object_array = []
          if records.is_a?(Array)
            records.each {|r| object_array << instantiate_object_from_record(r)}
          else 
            object_array = [instantiate_object_from_record(records)]
          end
          object_array
        end
        
        # Return a single SalesforceObject of the appropriate class given a RForce response hash
        def instantiate_single_object_from_query_response(response)
          record = extract_records_from_response(response)
          instantiate_object_from_record(record)
        end

        # Get a single hash or array of hashed records from inside an RForce response hash
        def extract_records_from_response(response)
          raise SimpleSalesforce::SalesforceQueryFaultException , "Salesforce returned a query fault: #{response[:Fault][:faultcode]} : #{response[:Fault][:faultstring]}", caller if response[:Fault]<commit_msg>Update finders to allow LIKE or = operators and also fix bug in returning empty result sets<commit_after>module SimpleSalesforce
  module SalesforceObject # :nodoc:

    module Finders
      
      def self.included(klass)
        klass.class_eval do
          extend ClassMethods
        end
      end
      
      module ClassMethods

        # Queries Salesforce and returns an instantiated object or an array of instantiated objects
        # Syntax find(:first, :conditions => {}), :find(:first, :conditions => ""), find(:all, :conditions => {}), find(:all, :conditions => "")
        def find(*args)
          options = args.extract_options!
          soql_conditions = construct_soql_conditions(options[:conditions])
          limit = options[:limit]
          case args.first
            when :all
              results = query_and_instantiate(:many, soql_conditions, limit)
            when :first
              results = query_and_instantiate(:one, soql_conditions, limit = 1)
            else
              # Find the object by its Salesforce Id and disregard :conditions and :limit
              # dontwork
              soql_conditions = construct_soql_conditions(:salesforce_id => args.first)
              results = query_and_instantiate(:one, soql_conditions, limit = 1)
            end
        end
        
        def method_missing(method_id, value)
          case method_id.to_s
            when /^find_(all_by|by)_([_a-zA-Z]\w*)$/
              finder = $1 == "all_by" ? :all : :first
              var = $2
              find(finder, :conditions => {var.to_sym => value})
            else
              super
          end
        end
        
        def query_and_instantiate(mode, soql_conditions, limit)
          # p construct_query_string(soql_conditions, limit) # debug
          query_response = SimpleSalesforce::Binding.binding.query :queryString => construct_query_string(soql_conditions, limit)
          case mode
          when :many
            instantiate_objects_from_query_response(query_response)
          when :one
            instantiate_single_object_from_query_response(query_response)
          end
        end
        
        # Figures out if the conditions are a single string (e.g. "Contact(FirstName) = 'Joe'") or a hash (e.g. #{:first_name => "Joe"})
        # If it's a hash, build the conditions out to SOQL
        def construct_soql_conditions(conditions = {})
          conditions = {} if conditions.nil?
          if conditions.is_a?(Hash)
            # It's a hash of conditions which we need to format, converting from local fieldnames to Salesforce object fieldnames in the process
            soql_conditions = format_conditions(conditions)
          else
            # It's probably a string, e.g. find(:all, :conditions => "Contact(FirstName) = 'Joe'")
            soql_conditions = [conditions]
          end
          soql_conditions.empty? ? [] : soql_conditions
        end
        
        # Returns an array of SOQL WHERE clause strings, given an array of hashes of the format #{:local_field => "value"}
        # This function interrogates the SalesforceObject Class to find the salesforce field for each local field
        def format_conditions(conditions)
          soql_conditions = []
          conditions.each do |local_field, value|
            salesforce_field = fields.select {|f| f[:field] == local_field.to_sym}.first[:salesforce_field] rescue nil
            operator = value.include?("%") ? "LIKE" : "="
            soql_conditions << "#{salesforce_field} #{operator} '#{value}'" unless salesforce_field.nil?
          end
          soql_conditions
        end

        # Construct SOQL query string from conditions array and limit number
        # The conditions array can be a single string or array of strings and will be joined with 'AND' if necessary
        def construct_query_string(soql_conditions, limit = nil)
          select_soql = "SELECT #{salesforce_fields.join(",")} "
          from_soql = "FROM #{salesforce_object_type}"
          where_soql = "#{' WHERE ' unless soql_conditions.empty?}#{soql_conditions.join(' AND ')}"
          limit_soql = "#{" LIMIT #{limit}" if limit}"
          "#{select_soql}#{from_soql}#{where_soql}#{limit_soql}"
        end
        
        # Return an array of SalesforceObjects of the appropriate class given a RForce response hash
        def instantiate_objects_from_query_response(response)
          records = extract_records_from_response(response)
          object_array = []
          if records.is_a?(Array)
            records.each {|r| object_array << instantiate_object_from_record(r)}
          elsif records.nil? 
            object_array = []
          else
            object_array = [instantiate_object_from_record(records)]
          end
          object_array
        end
        
        # Return a single SalesforceObject of the appropriate class given a RForce response hash
        def instantiate_single_object_from_query_response(response)
          record = extract_records_from_response(response)
          record.nil? ? nil : instantiate_object_from_record(record)
        end

        # Get a single hash or array of hashed records from inside an RForce response hash
        def extract_records_from_response(response)
          raise SimpleSalesforce::SalesforceQueryFaultException , "Salesforce returned a query fault: #{response[:Fault][:faultcode]} : #{response[:Fault][:faultstring]}", caller if response[:Fault]
{'fraction_non_alphanumeric': 0.08285235524110966, 'fraction_numerical': 0.0007447402718301992, 'mean_word_length': 2.4213375796178345, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5319311', 'n_tokens_mistral': 2859, 'n_tokens_neox': 2786, 'n_words': 806}