Class: SoqlData

Inherits:
Exchange
  • Object
show all
Extended by:
SoqlGlobalData, SoqlGlobalObjectData, SoqlObjectDescribe, SoqlSettings
Includes:
DataRelationships
Defined in:
lib/leap_salesforce/soql_data/soql_data.rb

Overview

Represents an API interaction via SOQL queries with the Salesforce database Usually this class is inherited by a class that represents a particular object, the only exception being the singleton methods in ‘SoqlGlobalData’

Instance Attribute Summary collapse

Attributes included from SoqlGlobalData

#ids_to_delete

Attributes included from SoqlGlobalObjectData

#ids_to_delete

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SoqlGlobalData

global_describe, limits

Methods included from SoqlGlobalObjectData

any?, delete_ids_with, id_where, ids_where, list, remove_dependent_records, soql, soql_element, where

Methods included from LeapSalesforce::Tooling

#run_test_asynchronous, #tooling_objects

Methods included from SoqlObjectDescribe

accessors, changes_from_date, default_for, description, field_names, fields, label_names, layouts, layouts_for, length_for, picklist_for, picklists, properties_for, relationship_name_for, required, type_for

Methods included from SoqlSettings

soql_object, soql_object_name

Methods included from DataRelationships

#organisation, #owner, #queue, #record_type

Constructor Details

#initialize(name = nil, http_parameters = {}) ⇒ SoqlData

Create a new SoqlData object. If override_parameters are empty then it’s assumed creation of an object is being done

Examples:

Create a new Contact step by step (Contact inherits from this class)

contact = Contact.new
contact.first_name = 'Bob'
contact.last_name = 'Smith'
contact.save! # API request made at this point

Create a Contact by specifying field names

contact = Contact.new first_name: 'Bob', last_name: 'Smith'
contact.save!

Create a contact using a factory with a trait of :email

contact_with_email = FactoryBot.create(:contact, :email)

Perform a get to the Salesforce limits api

SoqlData.new("Limits", method: :get, suburl: 'limits/')

Parameters:

  • name (String, Hash) (defaults to: nil)

    Name describing object. Defaults to itself. If Hash is provided with no ‘http_parameters’ then list will be fields to set on creating entity

  • http_parameters (Hash) (defaults to: {})

    Parameters used in making HTTP request. If creating a new object leave this to empty. Otherwise Hash would look like method: :get, suburl: ‘URL_AFTER_SOQL_HANDLER_BASE_URL’



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 47

def initialize(name = nil, http_parameters = {})
  super
  if @override_parameters && @override_parameters[:suburl]
    suburl_passed = @override_parameters[:suburl]
    @override_parameters[:suburl] = if suburl_passed.include?('sobjects')
                                      suburl_passed[suburl_passed.index('sobjects')..-1]
                                    else
                                      suburl_passed
                                    end
  end

  return unless http_parameters.empty?

  table_name = self.class.soql_object_name
  self.suburl = "sobjects/#{table_name}"
  optional_name = self.class.to_s == table_name ? '' : "(#{table_name})"
  self.test_name = "Factory for '#{self.class}'#{optional_name}" unless name
  return unless name.is_a? Hash

  name.dup.each do |field_name, field_value|
    send("#{field_name}=", field_value)
  end
end

Instance Attribute Details

#api_userString

Returns User used to make api calls.

Returns:

  • (String)

    User used to make api calls



78
79
80
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 78

def api_user
  @api_user
end

Class Method Details

.create(*factory_parameters) ⇒ Object

Create object using FactoryBot

Parameters:

  • factory_parameters (Hash)

    Parameters to pass to FactoryBot



73
74
75
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 73

def self.create(*factory_parameters)
  FactoryBot.create(to_s.snakecase.to_sym, *factory_parameters)
end

.descendantsClass

Returns descendants of the provided class SoqlData

Returns:

  • (Class)

    Classes that inherit from this class



256
257
258
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 256

def self.descendants
  ObjectSpace.each_object(Class).select { |class_name| class_name < self }
end

Instance Method Details

#[](backend_name) ⇒ String

Returns Value at backend name.

Returns:

  • (String)

    Value at backend name



201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 201

def [](backend_name)
  if @updated
    successful? unless backend_name.to_s == 'message' || backend_name.to_s == '$..message'
    @updated = false
    find # Retrieve data freshly after an update
  end
  value_from_path backend_name
rescue NoElementAtPath
  raise diagnose_error if error_message?

  find
  value_from_path backend_name
end

#[]=(key, value) ⇒ Object

Set a parameter request in the request body. Can be used to build a request over several steps (e.g Cucumber) Will be used with FactoryBot

Examples:

exchange['name'] = 'tester'
# Will set { name: tester } in the response, formatting as JSON or XML depending on REST / SOAP

Parameters:

  • key (String, Symbol)

    Name of request element to set

  • value (String)

    Value to set request element to



194
195
196
197
198
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 194

def []=(key, value)
  value = value.salesforce_format if value.is_a? Time
  @override_parameters[:body] ||= {}
  @override_parameters[:body][key] = value
end

#attach(filename) ⇒ Object

Add the passed in file as an attachment to the object



174
175
176
177
178
179
180
181
182
183
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 174

def attach(filename)
  unless defined? Attachment
    raise LeapSalesforce::SetupError, 'Attachment not defined. ' \
    "Add to '.leap_salesforce.yml' to use this"
  end
  raise LeapSalesforce::Error, "Filename #{filename} does not exist" unless File.exist? filename

  FactoryBot.create(:attachment, ParentId: id, Name: File.split(filename).last,
                                 body: Base64.encode64(File.read(filename)))
end

#delete(must_pass: false) ⇒ Exchange

Delete current record

Parameters:

  • must_pass (Boolean) (defaults to: false)

    Whether to raise exception if call is not successful

Returns:

  • (Exchange)

    Exchange object making delete



142
143
144
145
146
147
148
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 142

def delete(must_pass: false)
  sf_id = id
  self.class.delete(sf_id, must_pass: must_pass)
rescue NoElementAtPath
  LeapSalesforce.logger.warn "Tried to delete object that doesn't exist"
  self
end

#delete_as_admin(must_pass: true) ⇒ Exchange

Delete current record, switching to Admin before doing so

Parameters:

  • must_pass (Boolean) (defaults to: true)

    Whether to raise exception if call is not successful

Returns:

  • (Exchange)

    Exchange object making delete



153
154
155
156
157
158
159
160
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 153

def delete_as_admin(must_pass: true)
  LeapSalesforce.api_user = LeapSalesforce::Users.where key: :admin
rescue LeapSalesforce::UserError
  raise LeapSalesforce::SetupError, 'Please set up a user with a key of :admin' \
  'to use "delete_as_admin"'
else
  delete must_pass: must_pass
end

#diagnose_errorString, RestClient::Response

Returns Error message if present.

Returns:

  • (String, RestClient::Response)

    Error message if present



216
217
218
219
220
221
222
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 216

def diagnose_error
  return error_message if error_message?

  return response if @response # If response is made it would be helpful in diagnosing

  inspect # If no response, this may help
end

#error_messageString

Returns Error message if present. If not an error is raised.

Returns:

  • (String)

    Error message if present. If not an error is raised



230
231
232
233
234
235
236
237
238
239
240
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 230

def error_message
  if error_message?
    value_from_path :message
  else
    message = "No error message received. Status code is #{status_code}. "
    message += 'Response is successful when it should not be. ' if status_code.to_s[0] == '2'
    message += 'Response is empty' if response.to_s.empty?
    raise LeapSalesforce::ResponseError, message

  end
end

#error_message?Boolean

Returns Whether error message element is present.

Returns:

  • (Boolean)

    Whether error message element is present



225
226
227
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 225

def error_message?
  error_message_element?
end

#findExchange

Get details of itself by searching for it’s id Store response within itself

Returns:

  • (Exchange)

    Exchange with details of data



117
118
119
120
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 117

def find
  @response = self.class.find(Id: id).response # Make get call and store result
  self
end

#getExchange

Deprecated.

Get details of itself by searching for it’s id Store response within itself

Returns:

  • (Exchange)

    Exchange with details of data



126
127
128
129
130
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 126

def get
  LeapSalesforce.logger.warn "Method 'get' called when it is deprecated" \
  " from #{caller_locations[0]}"
  find
end

#idString

Extract the id or return the cached version of it

Returns:

  • (String)

    Id of Salesforce Object



102
103
104
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 102

def id
  @id ||= value_from_path '$..id,$..Id'
end

#idsArray

Returns List of ids from response.

Returns:

  • (Array)

    List of ids from response



169
170
171
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 169

def ids
  values_from_path('$..Id')
end

#no_retry=(set) ⇒ Object

Parameters:

  • set (Boolean)

    Whether to not retry for successful response (Used when you expect an error)



107
108
109
110
111
112
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 107

def no_retry=(set)
  return unless set

  # Set retry_count to 0 so if an invalid status code is returned a retry will not occur
  define_singleton_method('retry_count') { 0 }
end

#open_on_uiObject

Open Object on default browser



250
251
252
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 250

def open_on_ui
  Launchy.open("#{SoqlHandler.instance_url}/#{id}")
end

#success_update(data) ⇒ Object

Update current record with data provided expecting success

Parameters:

  • data (Hash)

    Data to update exchange with



164
165
166
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 164

def success_update(data)
  update(**data, must_pass: true)
end

#successful?True, LeapSalesforce::ResponseError

Returns Whether response is successful.

Returns:

Raises:



243
244
245
246
247
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 243

def successful?
  raise LeapSalesforce::ResponseError, "Error with updating #{self} #{diagnose_error}" unless (200..299).cover? status_code

  true
end

#unset=(element_to_unset, error: true) ⇒ Object

Unsets the element so it’s not set in the request at all (not just not setting it to empty) @todo: Allow mapping from ruby created field name to use as a parameter

Parameters:

  • element_to_unset (String, Symbol)

    Element to remove from being sent

  • error (Boolean) (defaults to: true)

    Whether to raise error if value to unset is not present



91
92
93
94
95
96
97
98
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 91

def unset=(element_to_unset, error: true)
  converted_element = element_to_unset.to_s
  unless @override_parameters[:body].key?(converted_element) && error
    raise LeapSalesforce::RequestError, "No backend name #{element_to_unset} in #{@override_parameters[:body]}\n" \
    "Valid values are #{@override_parameters[:body].keys}"
  end
  @override_parameters[:body].delete converted_element
end

#update(data) ⇒ Object

Update current record with data provided

Parameters:

  • data (Hash)

    Data to update exchange with



134
135
136
137
# File 'lib/leap_salesforce/soql_data/soql_data.rb', line 134

def update(data)
  @updated = true
  self.class.update(id, data)
end