Module: SalesforceArSync::SalesforceSync

Extended by:
ActiveSupport::Concern
Defined in:
lib/salesforce_ar_sync/salesforce_sync.rb

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#salesforce_skip_syncObject

if this instance variable is set to true, the salesforce_sync method will return without attempting to sync data to Salesforce



122
123
124
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 122

def salesforce_skip_sync
  @salesforce_skip_sync
end

Instance Method Details

#ar_sync_inbound_delete?Boolean

Check to see if the user passed in a true/false, if so return that, if not then they passed int a symbol to a method We then call the method and use its value instead

Returns:

  • (Boolean)


222
223
224
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 222

def ar_sync_inbound_delete?
  [true, false].include?(self.class.sync_inbound_delete) ? self.class.sync_inbound_delete : send(self.class.sync_inbound_delete)
end

#ar_sync_outbound_delete?Boolean

Returns:

  • (Boolean)


226
227
228
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 226

def ar_sync_outbound_delete?
  [true, false].include?(self.class.sync_outbound_delete) ? self.class.sync_outbound_delete : send(self.class.sync_outbound_delete)
end

#get_activerecord_web_idObject



266
267
268
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 266

def get_activerecord_web_id
  send(self.class.activerecord_web_id_attribute_name)
end

#is_boolean?(attribute) ⇒ Boolean

Returns:

  • (Boolean)


198
199
200
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 198

def is_boolean?(attribute)
  column_for_attribute(attribute) && column_for_attribute(attribute).type == :boolean
end

#salesforce_attributes_to_set(attributes = {}) ⇒ Object

An internal method used to get a hash of values that we are going to set from a Salesforce outbound message hash



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 135

def salesforce_attributes_to_set(attributes = {})
  {}.tap do |hash|
    # loop through the hash of attributes from the outbound message, and compare to our sf mappings and
    # create a reversed hash of value's and key's to pass to update_attributes
    attributes.each do |key, value|
      # make sure our sync_mapping contains the salesforce attribute AND that our object has a setter for it
      hash[self.class.salesforce_sync_attribute_mapping[key.to_s].to_sym] = value if self.class.salesforce_sync_attribute_mapping.include?(key.to_s) && respond_to?("#{self.class.salesforce_sync_attribute_mapping[key.to_s]}=")
    end

    # remove the web_id from hash if it exists, as we don't want to modify a web_id
    hash.delete(:id) if hash[:id]

    # update the sf_updated_at field with the system mod stamp from sf
    hash[:salesforce_updated_at] = attributes[:SystemModstamp]

    # incase we looked up via the WebId__c, we should set the salesforce_id
    hash[:salesforce_id] = attributes[self.class.salesforce_id_attribute_name]
  end
end

#salesforce_attributes_to_update(include_all = false, attrs = []) ⇒ Object

create a hash of updates to send to salesforce



184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 184

def salesforce_attributes_to_update(include_all = false, attrs = [])
  {}.tap do |hash|
    self.class.salesforce_sync_attribute_mapping.each do |key, value|
      next if (attrs.any? && attrs.exclude?(value.to_sym)) || !respond_to?(value)

      # Checkboxes in SFDC Cannot be nil.  Here we check for boolean field type and set nil values to be false
      attribute_value = send(value)
      attribute_value = false if is_boolean?(value) && attribute_value.nil?

      hash[key] = attribute_value if !self.class.readonly_fields&.include?(key.to_sym) && (include_all || salesforce_should_update_attribute?(value))
    end
  end
end

#salesforce_create_object(attributes) ⇒ Object



202
203
204
205
206
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 202

def salesforce_create_object(attributes)
  attributes[self.class.salesforce_web_id_attribute_name.to_s] = id if self.class.salesforce_sync_web_id? && !new_record?
  self.salesforce_id = SF_CLIENT.create!(salesforce_object_name, format_attributes(attributes))
  @exists_in_salesforce = true
end

#salesforce_delete_objectObject



214
215
216
217
218
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 214

def salesforce_delete_object
  if ar_sync_outbound_delete?
    SF_CLIENT.destroy!(salesforce_object_name, salesforce_id)
  end
end

#salesforce_empty_attributesObject

Salesforce completely excludes any empty/null fields from Outbound Messages We initialize all declared attributes as nil before mapping the values from the message



126
127
128
129
130
131
132
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 126

def salesforce_empty_attributes
  {}.tap do |hash|
    self.class.salesforce_sync_attribute_mapping.each do |key, _value|
      hash[key] = nil
    end
  end
end

#salesforce_object_exists?Boolean

Returns:

  • (Boolean)


173
174
175
176
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 173

def salesforce_object_exists?
  return @exists_in_salesforce if @exists_in_salesforce
  @exists_in_salesforce = !system_mod_stamp.nil?
end

#salesforce_perform_async_call?(attributes_to_update) ⇒ Boolean

if attributes specified in the async_attributes array are the only attributes being modified, then sync the data via delayed_job

Returns:

  • (Boolean)


232
233
234
235
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 232

def salesforce_perform_async_call?(attributes_to_update)
  return false if attributes_to_update.empty? || self.class.salesforce_async_attributes.empty?
  attributes_to_update.keys.all? { |key| self.class.salesforce_async_attributes.include?(key) } && salesforce_id.present?
end

#salesforce_process_update(attributes = {}) ⇒ Object

Gets passed the Salesforce outbound message hash of changed values and updates the corresponding model



156
157
158
159
160
161
162
163
164
165
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 156

def salesforce_process_update(attributes = {})
  attributes_to_update = salesforce_attributes_to_set(new_record? ? attributes : salesforce_empty_attributes.merge(attributes)) # only merge empty attributes for updates, so we don't overwrite the default create attributes
  attributes_to_update.each_pair do |k, v|
    send("#{k}=", v)
  end

  # we don't want to keep going in a endless loop.  SF has just updated these values.
  self.salesforce_skip_sync = true
  self.send(self.class.salesforce_save_method)
end

#salesforce_should_update_attribute?(attribute) ⇒ Boolean

Checks if the passed in attribute should be updated in Salesforce.com

Returns:

  • (Boolean)


179
180
181
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 179

def salesforce_should_update_attribute?(attribute)
  !respond_to?("#{attribute}_changed?") || (respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?"))
end

#salesforce_sync(*attrs) ⇒ Object

sync model data to Salesforce, adding any Salesforce validation errors to the models errors



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 238

def salesforce_sync(*attrs)
  return if salesforce_skip_sync?

  attributes_to_update = salesforce_attributes_to_update(attrs.any?, attrs)

  if salesforce_perform_async_call?(attributes_to_update)
    SalesforceArSync::SalesforceObjectSyncJob.set(priority: 50).perform_later(
      self.class.salesforce_web_class_name, salesforce_id,
      attributes_to_update.to_json
    )
  else
    if salesforce_object_exists?
      salesforce_update_object(attributes_to_update) if attributes_to_update.present?
    elsif salesforce_id.nil?
      salesforce_create_object(salesforce_attributes_to_update(!new_record?))
    end
  end
rescue Exception => ex
  errors.add(:base, ex.message)
  false
end

#salesforce_update_object(attributes) ⇒ Object



208
209
210
211
212
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 208

def salesforce_update_object(attributes)
  attributes[self.class.salesforce_web_id_attribute_name.to_s] = id if self.class.salesforce_sync_web_id? && !new_record?

  SF_CLIENT.update!(salesforce_object_name, format_attributes(attributes).merge(Id: salesforce_id))
end

#sync_web_idObject



260
261
262
263
264
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 260

def sync_web_id
  return false if !self.class.salesforce_sync_web_id? || SalesforceArSync.config['SYNC_ENABLED'] == false

  SF_CLIENT.update!(salesforce_object_name, Id: salesforce_id, self.class.salesforce_web_id_attribute_name.to_s => get_activerecord_web_id) if salesforce_id
end

#system_mod_stampObject

Finds a salesforce record by its Id and returns nil or its SystemModstamp



168
169
170
171
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 168

def system_mod_stamp
  sobject = SF_CLIENT.find(salesforce_object_name, salesforce_id)
  sobject.SystemModstamp
end