class LeapSalesforce::Soql
Handles interaction with Soql
, mapping ruby to soql query strings
Attributes
@return [SoqlData] Soql
table
Public Class Methods
@param [SoqlData] soql_table
Object
mapping to a Salesforce
table
# File lib/leap_salesforce/soql_data/soql.rb, line 10 def initialize(soql_table) self.soql_table = soql_table @default_filter = soql_table.instance_variable_get(:@default_filter) @soql_object_name = soql_table.soql_object_name end
Public Instance Methods
Returns SOQL condition for value passed to be used in SOQL query @example Greater than or equal to yesterday's date
condition_for("<=#{Time.mktime(2019,1,1)}") # => '<= 2019-01-01T00:00:00.000Z'
@param [String] field_name Backend field name @param [String, Object] value Value to search for. Certain characters modify this to be more of a complex
check. Object will be converted String if not already one
@return [String] Condition criteria to match value using SOQL
# File lib/leap_salesforce/soql_data/soql.rb, line 119 def condition_for(field_name, value) value = value.nil? ? 'null' : value.to_s operator, value = case value[0] when '>', '<', '!', 'I' then extract_comparator(value) when '~' then ['LIKE', value[1..-1]] else ['=', value] end case soql_table.type_for(field_name) when 'boolean', 'double', 'int' then "#{operator} #{value}" when 'date', 'datetime', 'time' unless value.type_of_time? raise LeapSalesforce::RequestError, "Value '#{value}' cannot be interpreted as date for #{field_name}" end "#{operator} #{value.to_zulu_date_string}" else # string, picklist, reference, id, textarea return "#{operator} #{value}" if operator.end_with?('IN') || value == 'null' "#{operator} '#{value}'" end end
@return [String] Created date if present
# File lib/leap_salesforce/soql_data/soql.rb, line 85 def created_date 'CreatedDate' if field_names.include?('CreatedDate') end
@param [Hash] lookup Hash representing look up performed @param [String] url Url to get
# File lib/leap_salesforce/soql_data/soql.rb, line 60 def data_from_url(url, lookup) soql_table.new("Id at #{url}", method: :get, suburl: url) rescue NoElementAtPath raise NoElementAtPath, "No result found for '#{lookup}' under user #{LeapSalesforce.api_user}" end
@param [String] value Value to extract comparator for @return [Array] Extract of operator, value, taking >, >, >= from string and rest of string
# File lib/leap_salesforce/soql_data/soql.rb, line 143 def extract_comparator(value) if value[1] == '=' [value[0..1], value[2..-1]] elsif value[0..2] == '!IN' ['NOT IN', value[3..-1].to_soql_array] elsif value[0..1] == 'IN' ['IN', value[2..-1].to_soql_array] elsif value[0] == 'I' # 'N' not 2nd character ['=', value] elsif value[0] == '!' remaining = value[1..-1] == 'nil' ? 'null' : value[1..-1] ['!=', remaining] else [value[0], value[1..-1]] end end
@return [Array]
# File lib/leap_salesforce/soql_data/soql.rb, line 90 def field_names soql_table.field_names end
Find the Salesforce
object using the lookup query provided. When id is returned it will look up the id directly, otherwise it will return an object referring to the list of results returned @return [> SoqlData] SoqlData
object that is the result of looking up id based on lookup criteria
# File lib/leap_salesforce/soql_data/soql.rb, line 20 def lookup_id(lookup) teardown = lookup.delete(:teardown) wait = lookup.delete(:wait) SoqlHandler.new("Query on #{self}").use result = if lookup.key? :Id soql_table.new("Lookup id: #{lookup[:Id]}", method: :get, suburl: "sobjects/#{@soql_object_name}/#{lookup[:Id]}") else query soql_id(lookup), wait: wait end SoqlData.ids_to_delete[self] = id if teardown result end
Map key to a field name if used directly or field defined through 'soql_element' @param [Symbol, String] key Key to map to Table field name @return [String] Field name of Salesforce
entity to use
# File lib/leap_salesforce/soql_data/soql.rb, line 97 def map_key(key) if field_names.include?(key.to_s) key.to_s elsif field_names.include?(key.to_s.camelize) key.to_s.camelize else soql_instance = soql_table.new return soql_instance.send("#{key}_element") if soql_instance.respond_to?("#{key}_element") raise LeapSalesforce::RequestError, "#{key} not in #{self}. " \ " Must be one of #{field_names} or a field name described in" \ " #{self}::FieldNames" end end
Perform SOQL query against Salesforce
Url encoding needs to be used when searching for special characters (+ => '%2B') (see www.w3schools.com/tags/ref_urlencode.asp) @param [String] soql_query String
representing SOQL query @param [Boolean] wait Whether to wait for record if no result returned @example Find an account with test organisation name
my_query = "SELECT Name from Account WHERE Name = 'TEST Org 001'" query my_query # => "SELECT+Name+from+Account+WHERE+Name+=+'TEST+Org+001'"
@return [self] Exchange object from which JSON response can be obtained (i.e, with exchange.response)
# File lib/leap_salesforce/soql_data/soql.rb, line 48 def query(soql_query, wait: false) rest_query = soql_query.gsub('%', '%25').gsub('+', '%2B').tr(' ', '+') query_object = soql_table.new("SOQL Query: #{soql_query}", method: :get, suburl: "query/?q=#{rest_query}") return query_object unless wait query_object.until(timeout: 20, interval: 1) do response.body.include? '"url"' # Could be waiting for element to be created end end
For dates (ending with .000Z), query is always greater than @param [Hash] lookup Hash to look up values according to @return [String] SOQL query to filter results
# File lib/leap_salesforce/soql_data/soql.rb, line 69 def soql_lookup_filter(lookup) limit = lookup.delete(:limit) @default_filter ||= lookup.delete(:order_by) || created_date conditional = '' lookup.each do |key, value| conditional_term = conditional.empty? ? 'WHERE' : 'AND' key_used = map_key key conditional += "#{conditional_term} #{key_used} #{condition_for(key_used, value)} " end query = conditional query += "ORDER BY #{@default_filter} DESC NULLS FIRST" if @default_filter query += " LIMIT #{limit}" if limit query end