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



74
75
76
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 74

def salesforce_skip_sync
  @salesforce_skip_sync
end

Instance Method Details

#is_boolean?(attribute) ⇒ Boolean

Returns:

  • (Boolean)


154
155
156
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 154

def is_boolean?(attribute)
  self.column_for_attribute(attribute) && self.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



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 87

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) && self.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) ⇒ Object

create a hash of updates to send to salesforce



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

def salesforce_attributes_to_update(include_all = false)
  {}.tap do |hash| 
    self.class.salesforce_sync_attribute_mapping.each do |key, value|
      if self.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 = self.send(value)
        if is_boolean?(value) && attribute_value.nil?
          attribute_value = false
        end

        hash[key] = attribute_value if include_all || salesforce_should_update_attribute?(value)
      end
    end
  end    
end

#salesforce_create_object(attributes) ⇒ Object



158
159
160
161
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 158

def salesforce_create_object(attributes)
  attributes.merge!(self.class.salesforce_web_id_attribute_name.to_s => id) if self.class.salesforce_sync_web_id? && !new_record?
  @sf_object = "Databasedotcom::#{self.salesforce_object_name}".constantize.create(attributes)
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



78
79
80
81
82
83
84
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 78

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_defaultObject

This method will fetch the salesforce object and go looking for it if it doesn’t exist



120
121
122
123
124
125
126
127
128
129
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 120

def salesforce_object_default
  return @sf_object if @sf_object.present?

  @sf_object = "Databasedotcom::#{self.salesforce_object_name}".constantize.send("find_by_#{self.class.salesforce_id_attribute_name.to_s}", salesforce_id) unless salesforce_id.nil?

  # Look up and link object by web id
  @sf_object ||= "Databasedotcom::#{self.salesforce_object_name}".constantize.send("find_by_#{self.class.salesforce_web_id_attribute_name.to_s}", id) if self.class.salesforce_sync_web_id? && !new_record?

  return @sf_object
end

#salesforce_perform_async_call?Boolean

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

Returns:

  • (Boolean)


170
171
172
173
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 170

def salesforce_perform_async_call?
  return false if salesforce_attributes_to_update.empty? || self.class.salesforce_async_attributes.empty?
  salesforce_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



108
109
110
111
112
113
114
115
116
117
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 108

def salesforce_process_update(attributes = {})
  attributes_to_update = salesforce_attributes_to_set(self.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|
    self.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.save!
end

#salesforce_should_update_attribute?(attribute) ⇒ Boolean

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

Returns:

  • (Boolean)


132
133
134
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 132

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

#salesforce_syncObject

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



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 176

def salesforce_sync
  return if self.salesforce_skip_sync?

  if salesforce_perform_async_call?
    Delayed::Job.enqueue(SalesforceArSync::SalesforceObjectSync.new(self.class.salesforce_web_class_name, self.salesforce_object_name, salesforce_id, salesforce_attributes_to_update), :priority => 50)
  else
    salesforce_update_object(salesforce_attributes_to_update) if salesforce_attributes_to_update.present? && salesforce_object
    salesforce_create_object(salesforce_attributes_to_update(!new_record?)) if salesforce_id.nil? && salesforce_object.nil?

    self.salesforce_id = salesforce_object.send(self.class.salesforce_id_attribute_name) unless salesforce_object.nil?
  end
rescue Exception => ex
  self.errors[:base] << ex.message
  return false
end

#salesforce_update_object(attributes) ⇒ Object



163
164
165
166
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 163

def salesforce_update_object(attributes)
  attributes.merge!(self.class.salesforce_web_id_attribute_name.to_s => id) if self.class.salesforce_sync_web_id? && !new_record?
  salesforce_object.update_attributes(attributes) if salesforce_object
end

#sync_web_idObject



192
193
194
195
# File 'lib/salesforce_ar_sync/salesforce_sync.rb', line 192

def sync_web_id
  return false if !self.class.salesforce_sync_web_id? || self.salesforce_skip_sync?
  salesforce_object.update_attribute(self.class.salesforce_web_id_attribute_name.to_s, id) if salesforce_id && salesforce_object
end