Search

Synchronizing SalesForce and Ruby on Rails

Derek

3 min read

Jul 26, 2006

Synchronizing SalesForce and Ruby on Rails

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
  1. the salesforce database specified in database.yml
    self.establish_connection :salesforce
    end

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.

Mark Dalrymple

Reviewer Big Nerd Ranch

MarkD is a long-time Unix and Mac developer, having worked at AOL, Google, and several start-ups over the years.  He’s the author of Advanced Mac OS X Programming: The Big Nerd Ranch Guide, over 100 blog posts for Big Nerd Ranch, and an occasional speaker at conferences. Believing in the power of community, he’s a co-founder of CocoaHeads, an international Mac and iPhone meetup, and runs the Pittsburgh PA chapter. In his spare time, he plays orchestral and swing band music.

Speak with a Nerd

Schedule a call today! Our team of Nerds are ready to help

Let's Talk

Related Posts

We are ready to discuss your needs.

Not applicable? Click here to schedule a call.

Stay in Touch WITH Big Nerd Ranch News