You need to sign in to do that
Don't have an account?

Update object with Ruby's SOAP
I'm building an adapter for Ruby's DataMapper for Salesforce. I've been able to use the WSDL with SOAP to make #query calls to Salesforce. However, I can't figure out how to use Ruby code to update an object (because Ruby's SOAP connector is not quite as snap-in as Java or C#'s connector).
The code I've been using to set up the connection is at: http://pastie.caboo.se/private/wcqjqv1icvshqpucsxupq
It's a little bit frustrating that Salesforce hung its Ruby hat on ActiveSalesforce, which is more a Rails/ActiveRecord solution than a general-purpose Ruby solution. Ideally, Salesforce would have built a low-level library to connect to its webservices, and then built ActiveSalesforce on top of it (the code for ASF is a mess, and includes a partial solution that someone was building prior to the release of ASF).
Anyhow, I'd appreciate any help someone could provide about making reliable #update calls back to the server for objects returned as a result of a #query call.
The code I've been using to set up the connection is at: http://pastie.caboo.se/private/wcqjqv1icvshqpucsxupq
It's a little bit frustrating that Salesforce hung its Ruby hat on ActiveSalesforce, which is more a Rails/ActiveRecord solution than a general-purpose Ruby solution. Ideally, Salesforce would have built a low-level library to connect to its webservices, and then built ActiveSalesforce on top of it (the code for ASF is a mess, and includes a partial solution that someone was building prior to the release of ASF).
Anyhow, I'd appreciate any help someone could provide about making reliable #update calls back to the server for objects returned as a result of a #query call.
ASF has been developed 100% on my own personal time as a labor of love initiated entirely out of curiosity - not a business need. At the time I initiated the project I did the same search that you've been going through to find something better than just the vanilla Ruby soap stack and that is when I found RForce which handled a number of the salesforce API specific bits. I've been relatively happy with what RForce provides - but I suspect our needs are different - I was building a generic adapter from Rails to any salesforce api exposed object (Partner API access) and I suspect you are looking for something that provides a type specific layer on top of the Enterprise API. With that said I am surprised that RForce is not a workable solution for you - it handles updates w/out any issues that I am aware of.
I am not actively developing ASF at this time and for the past 14 months I have been attempting to recruit contributors that would like to give something back to the project. The result of that is a few maybes and a lot of I would love to but can't find the time. I know that the author of RForce has also faced similar frustrations when he has asked for the community to put some skin in the game (neither one of us uses Ruby or RoR in our day jobs anymore). Perhaps you would like to ante up and help improve either RForce /or ASF? I'd be happy to train up anyone willing to roll up their sleeves and get their hands dirty.
Message Edited by dchasman on 04-10-2008 10:28 AM
Feel free to contact me at any of the following:
email: wycats@gmail.com
gtalk: wycats@gmail.com
IM: outlookeic
Phone: 718.877.1325
Thanks again,
-- Yehuda
RForce does not work for me. I am unable to login at all using RForce, but I am able to login with the SOAP::wsdlDriver.
Running the code below correctly returns the lead object, but I can't update it. I get the following error: #<SOAP::Mapping::Object:0x2654ddc>: INVALID_TYPE: Must send a concrete entity type. (SOAP::FaultError)
Any help would be greatly appreciated!:-)
#!/usr/bin/env ruby
require 'rubygems'
require "soap/wsdlDriver"
require 'soap/header/simplehandler'
require 'fastercsv'
# http://dev.ctor.org/soap4r/browser/trunk/sample/wsdl/salesforce/client.rb?rev=1609
class SessionHeaderHandler < SOAP::Header::SimpleHandler
HeaderName = XSD::QName.new('urn:enterprise.soap.sforce.com', 'SessionHeader')
attr_accessor :sessionid
def initialize
super(HeaderName)
@sessionid = nil
end
def on_simple_outbound
if @sessionid
{'sessionId' => @sessionid}
else
nil # no header
end
end
end
class CallOptionsHandler < SOAP::Header::SimpleHandler
HeaderName = XSD::QName.new('urn:enterprise.soap.sforce.com', 'CallOptions')
attr_accessor :client
def initialize
super(HeaderName)
@client = nil
end
def on_simple_outbound
if @client
{'client' => @client}
else
nil # no header
end
end
end
class SForce
def initialize
@driver = SOAP::WSDLDriverFactory.new(File.dirname(__FILE__) + '/salesforce_ent.wsdl').create_rpc_driver
@driver.options['protocol.http.ssl_config.verify_mode'] = OpenSSL::SSL::VERIFY_NONE
login = @driver.login(:username => 'XXXXX', :password => 'YYYYY')
@driver.endpoint_url = login.result.serverUrl
sessionid_handler = SessionHeaderHandler.new
sessionid_handler.sessionid = login.result.sessionId
@driver.headerhandler << sessionid_handler
calloptions_handler = CallOptionsHandler.new
calloptions_handler.client = 'client'
@driver.headerhandler << calloptions_handler
@driver.wiredump_dev = STDOUT
end
def query(string)
qr = @driver.query(:queryString => string)
num_results = qr.result.size.to_i
done = (num_results == 0)
while not done
done = qr.result.done
if num_results == 1
yield qr.result.records
else
qr.result.records.each do |record|
yield record
end
end
qr = @driver.queryMore(qr.result.queryLocator) unless done
end
end
def update(sObject)
res = @driver.update(:sObjects => [sObject])
end
end
sforce = SForce.new
sforce.query('select Id, Email, Invite_only_user__c from lead where email = \'foo@bar.com\'') do |l|
sforce.update(l)
end