heroku/databasedotcom — pull request #63 by eigenuser (2012-02-17 23:06:57+00:00)
Title: Support for interacting with multiple Salesforce organizations

Modified the reader and writer methods for `Databasedotcom::Sobject::Sobject.client` so they use a class-level instance variable rather than a class variable to store the client object.

To understand the problem this revision solves, consider the following scenario.

his_client = Databasedotcom::Client.new("databasedotcom.yml")
his_client.authenticate(:token => "his-oauth-token", :instance_url => "http://na1.salesforce.com")
his_client.sobject_module = His

her_client = Databasedotcom::Client.new("databasedotcom.yml")
her_client.authenticate(:token => "her-oauth-token", :instance_url => "http://na2.salesforce.com")
her_client.sobject_module = Her

his_client.materialize("HotDog") #=> His::HotDog
her_client.materialize("HotDog") #=> Her::HotDog

Her::HotDog.create({:bun => 'wheat', :meat => 'beef'}) #=> HotDog created in her Salesforce org

His::HotDog.create({:bun => 'white', :meat => 'chicken'}) #=> HotDog created in *her* Salesforce org!!!

This last line of code behaves in this unexpected way because both materialized classes `His::HotDog` and
`Her::HotDog` inherit from the `Databasedotcom::Sobject::Sobject` class, which uses a class variable
`@@client` to keep track of the `Databasedotcom::Client` object that was used to materialize the class.

Because Ruby class variables are shared across all subclasses, when the second HotDog class is materialized in
the `Her` module namespace and `Her::HotDog.client` is assigned the object instance `her_client`, the
assignment is in fact made to the `@@client` variable in the `Databasedotcom::Sobject::Sobject`
class. Consequently the change is reflected immediately in `His::HotDog.client` as well.

Thus, when the call to `His::HotDog.create` is made, the class is using `her_client` to send a POST to the
Salesforce instance server.

We can avoid this problem by using a class-level instance variable, instead of class variable, to store the
client object in an Sobject class.