Four Key Reasons to Learn Markdown
Back-End Leveling UpWriting documentation is fun—really, really fun. I know some engineers may disagree with me, but as a technical writer, creating quality documentation that will...
Salesforce, the large Customer Relationship Management tool, and Ruby on Rails, the elegant web development framework, seem like an awkward pair. About as awkward as dipping a Wendy’s french fry in a frosty.
Salesforce is large, often times confusing, and is a tool built for handling lots of different jobs. Rails is lean, elegant, and designed specifically for making web development easier. While Salesforce and Rails are dramatically different, they actually work very well together (much like a Wendy’s french fry dipped in a frosty – trust me).
This unlikely pairing is sparked by ActiveSalesforce, a Ruby on Rails connection adapter to Salesforce-managed data. This Ruby Gem makes working with Salesforce data about as easy as the Rails-MySQL combination.
Highgroove Studios is working on a Salesforce-Rails application, and one of the things we have to do is synchronize a local MySQL database with Salesforce. This is needed because the connection to Salesforce is slower than when working with a local database, and several parts of the application are time-sensitive.
Here’s a look at how we designed the application to synchronize data between the local database and Salesforce.
1. Abstract behaviors specific to Salesforce classes to a SalesforceRecord class.
class SalesforceRecord < ActiveRecord::Base self.abstract_class = true
2. Abstract behaviors for local representations of the Salesforce classes to an Acts::As::Syncable module. We’ll use meta programming to add this module’s functionality to our local classes.
# This module adds behaviors for syncing a local record # with a Salesforce record. module ActiveRecord module Acts #:nodoc: module Syncable #:nodoc: def self.included(base) base.extend(ClassMethods) end module ClassMethods # Use this method inside an ActiveRecord class # to add this module's behaviors. # Options: # - :with => Name of the native Salesforce # class that this class is synced with. # Ex: sync :with => Contact # Syncs this class with the +Contact+ class. def sync(options = {}) write_inheritable_attribute(:sync_options, { :with => options[:with] }) class_inheritable_reader :sync_options include ActiveRecord::Acts::Syncable::InstanceMethods end end module InstanceMethods end # InstanceMethods end # Syncable end # Acts end # ActiveRecord
config/environment.rb:
require 'acts_as_syncable' ActiveRecord::Base.send(:include, ActiveRecord::Acts::Syncable)
class Sfcontact < ActiveRecord::Base sync :with => Contact end
3. Add a method to send local updates to Salesforce.
When a Sfcontact logs in to our Rails application, we want to update the last login time in both the local and Salesforce database.
# Updates the +attribute+ and value of the local and does the same # for associated record in the Salesforce database if the # +sync :with+ option is provided. # No exceptions are raised if the connection to Salesforce can't # be established. def update_attribute_and_sync(attribute,value) if update_attribute(attribute,value) synced_class = sync_options[:with] # only sync if a Salesforce class is provided if synced_class.nil? raise "Can't sync with a Salesforce record unless it is specified with the sync :with option." # Turn into a Class if a String is passed elsif synced_class.is_a? String synced_class = kloned_class.constantize end # updated the synced attribute... # if we can't connect, don't raise an exception. begin synced_class.find_by_id(id).update_attribute(attribute,value) rescue SocketError logger.warn("Unable to connect to Salesforce and update [#{synced_class}] attribute [#{attribute}] with value [#{value}]") end end end # update_attribute_and_sync
Here’s how we update both the local database and Salesforce:
update_attribute_and_sync('last_login_at',Time.now)
Now we can synchronize and update from our local database to Salesforce by just adding a single line of code to our cloned Salesforce ActiveRecord classes.
Writing documentation is fun—really, really fun. I know some engineers may disagree with me, but as a technical writer, creating quality documentation that will...
Humanity has come a long way in its technological journey. We have reached the cusp of an age in which the concepts we have...
Go 1.18 has finally landed, and with it comes its own flavor of generics. In a previous post, we went over the accepted proposal and dove...