Restforce is a ruby gem for the Salesforce REST api. It's meant to be a lighter weight alternative to the databasedotcom gem.
It attempts to solve a couple of key issues that the databasedotcom gem has been unable to solve:
- Support for interacting with multiple users from different orgs.
- Support for parent-to-child relationships.
- Support for aggregate queries.
- Remove the need to materialize constants.
- Support for the Streaming API
- Support for blob data types.
- Support for GZIP compression.
- A clean and modular architecture using Faraday middleware
- Support for decoding Force.com Canvas signed requests. (NEW!)
Add this line to your application's Gemfile:
gem 'restforce'
And then execute:
$ bundle
Or install it yourself as:
$ gem install restforce
Restforce is designed with flexibility and ease of use in mind. By default, all api calls will
return Hashie::Mash objects,
so you can do things like client.query('select Id, (select Name from Children__r) from Account').Children__r.first.Name
.
Which authentication method you use really depends on your use case. If you're building an application where many users from different orgs are authenticated through oauth and you need to interact with data in their org on their behalf, you should use the OAuth token authentication method.
If you're using the gem to interact with a single org (maybe you're building some salesforce integration internally?) then you should use the username/password authentication method.
client = Restforce.new :oauth_token => 'oauth token',
:instance_url => 'instance url'
Although the above will work, you'll probably want to take advantage of the (re)authentication middleware by specifying a refresh token, client id and client secret:
client = Restforce.new :oauth_token => 'oauth token',
:refresh_token => 'refresh token',
:instance_url => 'instance url',
:client_id => 'client_id',
:client_secret => 'client_secret'
If you prefer to use a username and password to authenticate:
client = Restforce.new :username => 'foo',
:password => 'bar',
:security_token => 'security token'
:client_id => 'client_id',
:client_secret => 'client_secret'
You can connect to sandbox orgs by specifying a host. The default host is 'login.salesforce.com':
client = Restforce.new :host => 'test.salesforce.com'
You can set any of the options passed into Restforce.new globally:
Restforce.configure do |config|
config.client_id = ENV['SALESFORCE_CLIENT_ID']
config.client_secret = ENV['SALESFORCE_CLIENT_SECRET']
end
Performs a soql query and returns the result. The result will be a Restforce::Collection, which can be iterated over.
accounts = client.query("select Id, Something__c from Account where Id = 'someid'")
# => #<Restforce::Collection >
account = records.first
# => #<Restforce::SObject >
account.sobject_type
# => 'Account'
account.Id
# => "someid"
account.Name = 'Foobar'
account.save
# => true
account.destroy
# => true
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_query.htm
Performs a sosl query and returns the result. The result will be a Restforce::Collection.
# Find all occurrences of 'bar'
client.search('FIND {bar}')
# => #<Restforce::Collection >
# Find accounts match the term 'genepoint' and return the Name field
client.search('FIND {genepoint} RETURNING Account (Name)').map(&:Name)
# => ['GenePoint']
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_search.htm
Alias: insert
Takes an sobject name and a hash of attributes to create a record. Returns the Id of the newly created reocrd if the record was successfully created.
# Add a new account
client.create('Account', Name: 'Foobar Inc.')
# => '0016000000MRatd'
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_create.htm
Takes an sobject name and a hash of attributes to update a record. An 'Id' key is required in attrs (either a string or symbol). Returns true if the record was successfully updated.
# Update the Account with Id '0016000000MRatd'
client.update('Account', Id: '0016000000MRatd', Name: 'Whizbang Corp')
# => true
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_update_fields.htm
Takes an sobject name, an external id field, and a hash of attributes and either inserts or updates the record depending on the existince of the record. Returns true if the record was updated or the Id of the record if the record was created.
# Update the record with external ID of 12
client.upsert('Account', 'External__c', External__c: 12, Name: 'Foobar')
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_upsert.htm
Takes an sobject name and an Id and deletes the record. Returns true if the record was successfully deleted.
# Delete the Account with Id '0016000000MRatd'
client.destroy('Account', '0016000000MRatd')
# => true
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_delete_record.htm
If no parameter is given, it will return the global describe. If the name of an sobject is given, it will return the describe for that sobject.
# get the global describe for all sobjects
client.describe
# => { ... }
# get the describe for the Account object
client.describe('Account')
# => { ... }
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_describeGlobal.htm, http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_describe.htm
Performs an authentication and returns the response. In general, calling this directly shouldn't be required, since the client will handle authentication for you automatically. This should only be used if you want to force an authentication before using the streaming api, or you want to get some information about the user.
response = client.authenticate!
# => #<Restforce::Mash access_token="..." id="https://login.salesforce.com/id/00DE0000000cOGcMAM/005E0000001eM4LIAU" instance_url="https://na9.salesforce.com" issued_at="1348465359751" scope="api refresh_token" signature="3fW0pC/TEY2cjK5FCBFOZdjRtCfAuEbK1U74H/eF+Ho=">
# Get the user information
info = client.get(response.id).body
info.user_id
# => '005E0000001eM4LIAU'
Using the new Blob Data api feature (500mb limit):
client.create 'Document', FolderId: '00lE0000000FJ6H',
Description: 'Document test',
Name: 'My image',
Body: Restforce::UploadIO.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg'))
Using base64 encoded data (37.5mb limit):
client.create 'Document', FolderId: '00lE0000000FJ6H',
Description: 'Document test',
Name: 'My image',
Body: Base64::encode64(File.read('image.jpg'))
See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_insert_update_blob.htm
Restforce supports the Streaming API, and makes implementing pub/sub with Salesforce a trivial task:
# Restforce uses faye as the underlying implementation for CometD. I recommend
# using faye 0.8.3.
require 'faye'
# Initialize a client with your username/password/oauth token/etc.
client = Restforce.new
# Force an authentication request.
client.authenticate!
# Create a PushTopic for subscribing to Account changes.
client.create! 'PushTopic', {
ApiVersion: '23.0',
Name: 'AllAccounts',
Description: 'All account records',
NotifyForOperations: 'All',
NotifyForFields: 'All',
Query: "select Id from Account"
}
EM.run {
# Subscribe to the PushTopic.
client.subscribe 'AllAccounts' do |message|
puts message.inspect
end
}
Boom, you're now receiving push notifications when Accounts are created/updated.
See also: http://www.salesforce.com/us/developer/docs/api_streaming/index.htm
The gem supports easy caching of GET requests (e.g. queries):
# rails example:
client = Restforce.new cache: Rails.cache
# or
Restforce.configure do |config|
config.cache = Rails.cache
end
If you enable caching, you can disable caching on a per-request basis by using .without_caching:
client.without_caching do
client.query('select Id from Account')
end
You can easily inspect what Restforce is sending/receiving by setting
Restforce.log = true
.
Restforce.log = true
client = Restforce.new.query('select Id, Name from Account')
Another awesome feature about restforce is that, because it is based on Faraday, you can insert your own middleware. For example, if you were using Restforce in a rails app, you can setup custom logging using ActiveSupport::Notifications:
client = Restforce.new
client.middleware.insert_after Restforce::Middleware::InstanceURL, FaradayMiddleware::Instrumentation
# config/initializers/notifications.rb
ActiveSupport::Notifications.subscribe('request.faraday') do |name, start, finish, id, payload|
Rails.logger.debug(['notification:', name, "#{(finish - start) * 1000}ms", payload[:status]].join(" "))
end
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request