Class: LeapSalesforce::Soql

Inherits:
Object
  • Object
show all
Defined in:
lib/leap_salesforce/soql_data/soql.rb

Overview

Handles interaction with Soql, mapping ruby to soql query strings

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(soql_table) ⇒ Soql

Returns a new instance of Soql.

Parameters:

  • soql_table (SoqlData)

    Object mapping to a Salesforce table



10
11
12
13
14
# 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

Instance Attribute Details

#soql_tableSoqlData

Returns Soql table.

Returns:



7
8
9
# File 'lib/leap_salesforce/soql_data/soql.rb', line 7

def soql_table
  @soql_table
end

Instance Method Details

#condition_for(field_name, value) ⇒ String

Returns SOQL condition for value passed to be used in SOQL query

Examples:

Greater than or equal to yesterday’s date

condition_for("<=#{Time.mktime(2019,1,1)}") # => '<= 2019-01-01T00:00:00.000Z'

Parameters:

  • field_name (String)

    Backend field name

  • value (String, Object)

    Value to search for. Certain characters modify this to be more of a complex check. Object will be converted String if not already one

Returns:

  • (String)

    Condition criteria to match value using SOQL



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# 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

#created_dateString

Returns Created date if present.

Returns:

  • (String)

    Created date if present



85
86
87
# File 'lib/leap_salesforce/soql_data/soql.rb', line 85

def created_date
  'CreatedDate' if field_names.include?('CreatedDate')
end

#data_from_url(url, lookup) ⇒ Object

Parameters:

  • lookup (Hash)

    Hash representing look up performed

  • url (String)

    Url to get



60
61
62
63
64
# 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

#extract_comparator(value) ⇒ Array

Returns Extract of operator, value, taking >, >, >= from string and rest of string.

Parameters:

  • value (String)

    Value to extract comparator for

Returns:

  • (Array)

    Extract of operator, value, taking >, >, >= from string and rest of string



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# 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

#field_namesArray

Returns:

  • (Array)


90
91
92
# File 'lib/leap_salesforce/soql_data/soql.rb', line 90

def field_names
  soql_table.field_names
end

#lookup_id(lookup) ⇒ Object

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

Returns:

  • > SoqlData

    SoqlData object that is the result of looking up id based on lookup criteria



20
21
22
23
24
25
26
27
28
29
30
31
# 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(key) ⇒ String

Map key to a field name if used directly or field defined through ‘soql_element’

Parameters:

  • key (Symbol, String)

    Key to map to Table field name

Returns:

  • (String)

    Field name of Salesforce entity to use



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# 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

#query(soql_query, wait: false) ⇒ self

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)

Examples:

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'"

Parameters:

  • soql_query (String)

    String representing SOQL query

  • wait (Boolean) (defaults to: false)

    Whether to wait for record if no result returned

Returns:

  • (self)

    Exchange object from which JSON response can be obtained (i.e, with exchange.response)



48
49
50
51
52
53
54
55
56
# 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

#soql_id(lookup) ⇒ String

Returns String to find soql object based on criteria.

Parameters:

  • lookup (Hash)

    Hash to find Soql object via

Returns:

  • (String)

    String to find soql object based on criteria



35
36
37
# File 'lib/leap_salesforce/soql_data/soql.rb', line 35

def soql_id(lookup)
  "SELECT Id FROM #{@soql_object_name} #{soql_lookup_filter(lookup)}"
end

#soql_lookup_filter(lookup) ⇒ String

For dates (ending with .000Z), query is always greater than

Parameters:

  • lookup (Hash)

    Hash to look up values according to

Returns:

  • (String)

    SOQL query to filter results



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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