<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>The Napkin ~ A Blog By Highgroove Studios comments on Synchronizing SalesForce and Ruby on Rails</title>
    <link>http://cleanair.highgroove.com/</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>The Napkin ~ A Blog By Highgroove Studios comments</description>
    <item>
      <title>"Synchronizing SalesForce and Ruby on Rails": comment by Nick Selvaggio</title>
      <description>&lt;p&gt;Interesting. I second the Wendy&amp;#8217;s french fries dipped into a frosty!&lt;/p&gt;</description>
      <pubDate>Thu, 27 Jul 2006 16:16:54 EST</pubDate>
      <guid>http://cleanair.highgroove.com/articles/2006/07/27/synchorizing-a-salesforce-and-ruby-on-rails-database#comment-31</guid>
      <link>http://cleanair.highgroove.com/articles/2006/07/27/synchorizing-a-salesforce-and-ruby-on-rails-database#comment-31</link>
    </item>
    <item>
      <title>"Synchronizing SalesForce and Ruby on Rails" by derek</title>
      <description>&lt;p&gt;&lt;a href="http://www.salesforce.com"&gt;Salesforce&lt;/a&gt;, the large Customer Relationship Management tool, and &lt;a href="http://www.rubyonrails.com"&gt;Ruby on Rails&lt;/a&gt;, the elegant web development framework, seem like an awkward pair. About as awkward as dipping a Wendy&amp;#8217;s french fry in a frosty.&lt;/p&gt;


	&lt;p&gt;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&amp;#8217;s french fry dipped in a frosty &amp;#8211; trust me).&lt;/p&gt;


	&lt;p&gt;This unlikely pairing is sparked by &lt;a href="http://activesfdc.rubyforge.org/"&gt;ActiveSalesforce&lt;/a&gt;, 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.&lt;/p&gt;


	&lt;p&gt;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.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s a look at how we designed the application to synchronize data between the local database and Salesforce.&lt;/p&gt;

&lt;strong&gt;1. Abstract behaviors specific to Salesforce classes to a SalesforceRecord class.&lt;/strong&gt;
&lt;pre&gt;&lt;code&gt;
class SalesforceRecord &amp;lt; ActiveRecord::Base
  self.abstract_class = true
  # the salesforce database specified in database.yml
  self.establish_connection :salesforce
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;2. Abstract behaviors for local representations of the Salesforce classes to an Acts::As::Syncable module.&lt;/strong&gt; We&amp;#8217;ll use meta programming to add this module&amp;#8217;s functionality to our local classes.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://cleanair.highgroove.com/images/icons/download.png" alt="" /&gt; &lt;a href="http://cleanair.highgroove.com/files/acts_as_syncable.txt"&gt;Download the final Acts::As::Syncable Module [TXT]&lt;/a&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# 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 =&amp;gt; Name of the native Salesforce 
         #               class that this class is synced with. 
         #               Ex: sync :with =&amp;gt; Contact
         #               Syncs this class with the +Contact+ class.
         def sync(options = {})
            write_inheritable_attribute(:sync_options, {
              :with =&amp;gt; options[:with]
            })

            class_inheritable_reader :sync_options

            include ActiveRecord::Acts::Syncable::InstanceMethods        
          end
      end

      module InstanceMethods

      end # InstanceMethods
    end # Syncable
  end # Acts
end # ActiveRecord
&lt;/code&gt;&lt;/pre&gt;

config/environment.rb:
&lt;pre&gt;&lt;code&gt;
require 'acts_as_syncable'
ActiveRecord::Base.send(:include, ActiveRecord::Acts::Syncable)
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;
class Sfcontact &amp;lt; ActiveRecord::Base
  sync :with =&amp;gt; Contact
end
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;3. Add a method to send local updates to Salesforce.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;When a Sfcontact logs in to our Rails application, we want to update the last login time in both the local and Salesforce database.&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
# 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
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Here&amp;#8217;s how we update both the local database and Salesforce:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
update_attribute_and_sync('last_login_at',Time.now)
&lt;/pre&gt;&lt;/code&gt;

	&lt;p&gt;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.&lt;/p&gt;</description>
      <pubDate>Thu, 27 Jul 2006 11:50:00 EST</pubDate>
      <guid>&lt;a href="/articles/2006/07/27/synchorizing-a-salesforce-and-ruby-on-rails-database"&gt;Synchronizing SalesForce and Ruby on Rails&lt;/a&gt;</guid>
      <link>&lt;a href="/articles/2006/07/27/synchorizing-a-salesforce-and-ruby-on-rails-database"&gt;Synchronizing SalesForce and Ruby on Rails&lt;/a&gt;</link>
    </item>
  </channel>
</rss>
