Code Monkey home page Code Monkey logo

force.rb's Introduction

Force

A ruby gem for the Salesforce REST api.

Features

  • A clean and modular architecture using Faraday middleware and Hashie::Mash'd responses.
  • Support for interacting with multiple users from different orgs.
  • Support for parent-to-child relationships.
  • Support for aggregate queries.
  • Support for the Streaming API
  • Support for blob data types.
  • Support for GZIP compression.
  • Support for custom Apex REST endpoints.
  • Support for dependent picklists.
  • Support for decoding Force.com Canvas signed requests. (NEW!)

Installation

Add this line to your application's Gemfile:

gem 'force'

And then execute:

$ bundle

Or install it yourself as:

$ gem install force

Usage

Force 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.

Initialization

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.

OAuth Token Authentication

client = Force.new :instance_url => 'xx.salesforce.com',
                   :oauth_token => '...'

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 = Force.new :instance_url => 'xx.salesforce.com',
                   :oauth_token => '...',
                   :refresh_token => '...',
                   :client_id => '...',
                   :client_secret => '...'

Username/Password authentication

If you prefer to use a username and password to authenticate:

client = Force.new :username => '[email protected]',
                   :password => '...',
                   :security_token => '...',
                   :client_id => '...',
                   :client_secret => '...'

You can also set the username, password, security token, client id and client secret in environment variables:

export SALESFORCE_USERNAME="username"
export SALESFORCE_PASSWORD="password"
export SALESFORCE_SECURITY_TOKEN="security token"
export SALESFORCE_CLIENT_ID="client id"
export SALESFORCE_CLIENT_SECRET="client secret"
client = Force.new

Proxy Support

You can specify a http proxy using the :proxy_uri option, as follows:

client = Force.new :proxy_uri => 'http://proxy.example.com:123'

This paramter also will accept http://user@password:proxy.example.com:123 or using the environemnt variable PROXY_URI.

Sandbox Orgs

You can connect to sandbox orgs by specifying a host. The default host is login.salesforce.com:

client = Force.new :host => 'test.salesforce.com'

The host can also be set with the environment variable SALESFORCE_HOST.

Global Configuration

You can set any of the options passed into Force.new globally:

Force.configure do |config|
  config.client_id = 'foo'
  config.client_secret = 'bar'
end

query

accounts = client.query("select Id, Something__c from Account where Id = 'someid'")
# => #<Force::Collection >

account = accounts.first
# => #<Force::SObject >

account.sobject_type
# => 'Account'

account.Id
# => "someid"

account.Name = 'Foobar'
account.save
# => true

account.destroy
# => true

find

client.find('Account', '001D000000INjVe')
# => #<Force::SObject Id="001D000000INjVe" Name="Test" LastModifiedBy="005G0000002f8FHIAY" ... >

client.find('Account', '1234', 'Some_External_Id_Field__c')
# => #<Force::SObject Id="001D000000INjVe" Name="Test" LastModifiedBy="005G0000002f8FHIAY" ... >

search

# Find all occurrences of 'bar'
client.search('FIND {bar}')
# => #<Force::Collection >

# Find accounts match the term 'genepoint' and return the Name field
client.search('FIND {genepoint} RETURNING Account (Name)').map(&:Name)
# => ['GenePoint']

create

client.create('Account', Name: 'Foobar Inc.') # => '0016000000MRatd'

update

client.update('Account', Id: '0016000000MRatd', Name: 'Whizbang Corp') # => true

upsert

client.upsert('Account', 'External__c', External__c: 12, Name: 'Foobar') # => true

destroy

client.destroy('Account', '0016000000MRatd') # => true

All the CRUD methods (create, update, upsert, destroy) have equivalent methods with a ! at the end (create!, update!, upsert!, destroy!), which can be used if you need to do some custom error handling. The bang methods will raise exceptions, while the non-bang methods will return false in the event that an exception is raised.

describe

client.describe # => { ... }
client.describe('Account') # => { ... }

describe_layouts

client.describe_layout('Account') # => { ... }
client.describe_layouts('Account', '012E0000000RHEp') # => { ... }

picklist_values

client.picklist_values('Account', 'Type') # => [#<Force::Mash label="Prospect" value="Prospect">]

# Given a custom object named Automobile__c
#   with picklist fields Model__c and Make__c,
#   where Model__c depends on the value of Make__c.
client.picklist_values('Automobile__c', 'Model__c', :valid_for => 'Honda')
# => [#<Force::Mash label="Civic" value="Civic">, ... ]

authenticate!

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!
# => #<Force::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'

File Uploads

Using the new Blob Data api feature (500mb limit):

image = Force::UploadIO.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg')
client.create 'Document', FolderId: '00lE0000000FJ6H',
                          Description: 'Document test',
                          Name: 'My image',
                          Body: image)

Using base64-encoded data (37.5mb limit):

data = Base64::encode64(File.read('image.jpg')
client.create 'Document', FolderId: '00lE0000000FJ6H',
                          Description: 'Document test',
                          Name: 'My image',
                          Body: data)

See also: http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_insert_update_blob.htm

Downloading Attachments

Force also makes it incredibly easy to download Attachments:

attachment = client.query('select Id, Name, Body from Attachment').first
File.open(attachment.Name, 'wb') { |f| f.write(attachment.Body) }

Custom Apex REST endpoints

You can use Force to interact with your custom REST endpoints, by using .get, .put, .patch, .post, and .delete.

For example, if you had the following Apex REST endpoint on Salesforce:

@RestResource(urlMapping='/FieldCase/*')
global class RESTCaseController {
  @HttpGet
  global static List<Case> getOpenCases() {
    String companyName = RestContext.request.params.get('company');
    Account company = [ Select ID, Name, Email__c, BillingState from Account where Name = :companyName];

    List<Case> cases = [SELECT Id, Subject, Status, OwnerId, Owner.Name from Case WHERE AccountId = :company.Id];
    return cases;
  }
}

...then you could query the cases using Force:

client.get '/services/apexrest/FieldCase', :company => 'GenePoint'
# => #<Force::Collection ...>

Streaming

Force supports the Streaming API, and makes implementing pub/sub with Salesforce a trivial task:

# Force uses faye as the underlying implementation for CometD.
require 'faye'

# Initialize a client with your username/password/oauth token/etc.
client = Force.new :username => 'foo',
  :password       => 'bar',
  :security_token => 'security token'
  :client_id      => 'client_id',
  :client_secret  => 'client_secret'

# 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
}

See also: http://www.salesforce.com/us/developer/docs/api_streaming/index.htm


Caching

The gem supports easy caching of GET requests (e.g. queries):

# rails example:
client = Force.new cache: Rails.cache

# or
Force.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

Logging / Debugging / Instrumenting

You can inspect what Force is sending/receiving by setting Force.log = true.

Force.log = true
client = Force.new.query('select Id, Name from Account')

Another awesome feature about force is that, because it is based on Faraday, you can insert your own middleware.

For example, if you were using Force in a Rails app, you can setup custom reporting to Librato using ActiveSupport::Notifications:

client = Force.new do |builder|
  builder.insert_after Force::Middleware::InstanceURL,
                       FaradayMiddleware::Instrumentation, name: 'request.salesforce'
end

config/initializers/notifications.rb

ActiveSupport::Notifications.subscribe('request.salesforce') do |*args|
  event = ActiveSupport::Notifications::Event.new(*args)
  Librato.increment 'api.salesforce.request.total'
  Librato.timing 'api.salesforce.request.time', event.duration
end

Force.com Canvas

You can use Force to decode signed requests from Salesforce. See the example app.

Tooling API

To use the Tooling API, call Force.tooling instead of Force.new:

client = Force.tooling(...)

Security note

Always sanitize your raw SOQL queries. To avoid SQL-injection (in this case, SOSQL-injection) attacks. Given the syntax similarities between SQL and SOQL, Salesforce recommends using ActiveRecord's sanitization methods.


Contact

License

Force is available under the MIT license. See the LICENSE file for more info.

force.rb's People

Contributors

ejholmes avatar mattt avatar nahiluhmot avatar chulkilee avatar eloyesp avatar lukesutton avatar kidd avatar raul avatar cobraextreme avatar

Watchers

vincent spehner avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.