restforce 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of restforce might be problematic. Click here for more details.

data/README.md CHANGED
@@ -47,7 +47,7 @@ authentication method.
47
47
  #### OAuth token authentication
48
48
 
49
49
  ```ruby
50
- client = Restforce::Client.new :oauth_token => 'oauth token',
50
+ client = Restforce.new :oauth_token => 'oauth token',
51
51
  :instance_url => 'instance url'
52
52
  ```
53
53
 
@@ -55,7 +55,7 @@ Although the above will work, you'll probably want to take advantage of the
55
55
  (re)authentication middleware by specifying a refresh token, client id and client secret:
56
56
 
57
57
  ```ruby
58
- client = Restforce::Client.new :oauth_token => 'oauth token',
58
+ client = Restforce.new :oauth_token => 'oauth token',
59
59
  :refresh_token => 'refresh token',
60
60
  :instance_url => 'instance url',
61
61
  :client_id => 'client_id',
@@ -67,7 +67,7 @@ client = Restforce::Client.new :oauth_token => 'oauth token',
67
67
  If you prefer to use a username and password to authenticate:
68
68
 
69
69
  ```ruby
70
- client = Restforce::Client.new :username => 'foo',
70
+ client = Restforce.new :username => 'foo',
71
71
  :password => 'bar',
72
72
  :security_token => 'security token'
73
73
  :client_id => 'client_id',
@@ -80,12 +80,12 @@ You can connect to sandbox orgs by specifying a host. The default host is
80
80
  'login.salesforce.com':
81
81
 
82
82
  ```ruby
83
- client = Restforce::Client.new :host => 'test.salesforce.com'
83
+ client = Restforce.new :host => 'test.salesforce.com'
84
84
  ```
85
85
 
86
86
  #### Global configuration
87
87
 
88
- You can set any of the options passed into Restforce::Client.new globally:
88
+ You can set any of the options passed into Restforce.new globally:
89
89
 
90
90
  ```ruby
91
91
  Restforce.configure do |config|
@@ -185,7 +185,7 @@ pub/sub with Salesforce a trivial task:
185
185
 
186
186
  ```ruby
187
187
  # Initialize a client with your username/password/oauth token/etc
188
- client = Restforce::Client.new
188
+ client = Restforce.new
189
189
 
190
190
  # Force an authentication request
191
191
  client.authenticate!
@@ -201,6 +201,53 @@ EM.run {
201
201
  Boom, you're now receiving push notifications when Accounts are
202
202
  created/updated.
203
203
 
204
+ ### Caching
205
+
206
+ The gem supports easy caching of GET requests (e.g. queries):
207
+
208
+ ```ruby
209
+ # Memcached example:
210
+
211
+ cache = Dalli::Client.new
212
+
213
+ client = Restforce.new cache: cache
214
+
215
+ # or
216
+
217
+ Restforce.configure do |config|
218
+ config.cache = cache
219
+ end
220
+ ```
221
+
222
+ ### Logging/Debugging
223
+
224
+ You can easily inspect what Restforce is sending/receiving by setting
225
+ `Restforce.log = true`.
226
+
227
+ ```ruby
228
+ Restforce.log = true
229
+ client = Restforce.new.query('select Id, Name from Account')
230
+
231
+ # => I, [2012-09-11T21:54:00.488991 #24032] INFO -- : post https://login.salesforce.com/services/oauth2/token
232
+ # => D, [2012-09-11T21:54:00.489078 #24032] DEBUG -- request:
233
+ # => I, [2012-09-11T21:54:00.997295 #24032] INFO -- Status: 200
234
+ # => D, [2012-09-11T21:54:00.997391 #24032] DEBUG -- response headers: server: ""
235
+ # => content-type: "application/json; charset=UTF-8"
236
+ # => transfer-encoding: "chunked"
237
+ # => date: "Wed, 12 Sep 2012 04:53:59 GMT"
238
+ # => connection: "close"
239
+ # => D, [2012-09-11T21:54:00.997431 #24032] DEBUG -- response body: { ... }
240
+ # => I, [2012-09-11T21:54:00.998985 #24032] INFO -- : get https://na9.salesforce.com/services/data/v24.0/query?q=select+Id%2C+Name+from+Account
241
+ # => D, [2012-09-11T21:54:00.999040 #24032] DEBUG -- request: Authorization: "OAuth token"
242
+ # => I, [2012-09-11T21:54:01.622874 #24032] INFO -- Status: 200
243
+ # => D, [2012-09-11T21:54:01.623001 #24032] DEBUG -- response headers: server: ""
244
+ # => content-type: "application/json; charset=UTF-8"
245
+ # => transfer-encoding: "chunked"
246
+ # => date: "Wed, 12 Sep 2012 04:54:00 GMT"
247
+ # => connection: "close"
248
+ # => D, [2012-09-11T21:54:01.623058 #24032] DEBUG -- response body: { ... }
249
+ ```
250
+
204
251
  ## Contributing
205
252
 
206
253
  1. Fork it
@@ -14,6 +14,15 @@ require 'restforce/client'
14
14
  require 'restforce/middleware'
15
15
 
16
16
  module Restforce
17
+ class << self
18
+ # Alias for Restforce::Client.new
19
+ #
20
+ # Shamelessly pulled from https://github.com/pengwynn/octokit/blob/master/lib/octokit.rb
21
+ def new(options = {})
22
+ Restforce::Client.new(options)
23
+ end
24
+ end
25
+
17
26
  class AuthenticationError < StandardError; end
18
27
  class UnauthorizedError < StandardError; end
19
28
  class InstanceURLError < StandardError; end
@@ -52,7 +52,7 @@ module Restforce
52
52
  raise 'Please specify a hash of options' unless options.is_a?(Hash)
53
53
  @options = {}.tap do |options|
54
54
  [:username, :password, :security_token, :client_id, :client_secret, :host,
55
- :api_version, :oauth_token, :refresh_token, :instance_url].each do |option|
55
+ :api_version, :oauth_token, :refresh_token, :instance_url, :cache].each do |option|
56
56
  options[option] = Restforce.configuration.send option
57
57
  end
58
58
  end
@@ -327,8 +327,9 @@ module Restforce
327
327
  builder.use Restforce::Middleware::Authorization, self, @options
328
328
  builder.use Restforce::Middleware::InstanceURL, self, @options
329
329
  builder.use Restforce::Middleware::RaiseError
330
- builder.response :logger, Restforce.configuration.logger if Restforce.log?
331
330
  builder.response :json
331
+ builder.use Restforce::Middleware::Caching, cache if cache
332
+ builder.use Restforce::Middleware::Logger, Restforce.configuration.logger if Restforce.log?
332
333
  builder.adapter Faraday.default_adapter
333
334
  end
334
335
  @connection
@@ -361,6 +362,11 @@ module Restforce
361
362
  @options[:client_secret]
362
363
  end
363
364
 
365
+ # Internal: Cache to use for the caching middleware
366
+ def cache
367
+ @options[:cache]
368
+ end
369
+
364
370
  # Internal: Returns true if the middlware stack includes the
365
371
  # Restforce::Middleware::Mashify middleware.
366
372
  def mashify?
@@ -56,6 +56,10 @@ module Restforce
56
56
  attr_accessor :refresh_token
57
57
  attr_accessor :instance_url
58
58
 
59
+ # Set this to an object that responds to read, write and fetch and all GET
60
+ # requests will be cached.
61
+ attr_accessor :cache
62
+
59
63
  def initialize
60
64
  @api_version ||= '24.0'
61
65
  @host ||= 'login.salesforce.com'
@@ -29,3 +29,5 @@ require 'restforce/middleware/authorization'
29
29
  require 'restforce/middleware/instance_url'
30
30
  require 'restforce/middleware/mashify'
31
31
  require 'restforce/middleware/multipart'
32
+ require 'restforce/middleware/caching'
33
+ require 'restforce/middleware/logger'
@@ -23,7 +23,7 @@ module Restforce
23
23
  def connection
24
24
  @connection ||= Faraday.new(:url => "https://#{@options[:host]}") do |builder|
25
25
  builder.response :json
26
- builder.response :logger, Restforce.configuration.logger if Restforce.log?
26
+ builder.use Restforce::Middleware::Logger, Restforce.configuration.logger if Restforce.log?
27
27
  builder.adapter Faraday.default_adapter
28
28
  end
29
29
  end
@@ -31,6 +31,10 @@ module Restforce
31
31
  def force_authenticate?(env)
32
32
  env[:request_headers] && env[:request_headers]['X-ForceAuthenticate']
33
33
  end
34
+
35
+ def error_message(response)
36
+ "#{response.body['error']}: #{response.body['error_description']}"
37
+ end
34
38
 
35
39
  end
36
40
 
@@ -13,7 +13,7 @@ module Restforce
13
13
  :password => password
14
14
  )
15
15
  end
16
- raise Restforce::AuthenticationError if response.status != 200
16
+ raise Restforce::AuthenticationError, error_message(response) if response.status != 200
17
17
  @options[:instance_url] = response.body['instance_url']
18
18
  @options[:oauth_token] = response.body['access_token']
19
19
  end
@@ -12,7 +12,7 @@ module Restforce
12
12
  :client_secret => @options[:client_secret]
13
13
  )
14
14
  end
15
- raise Restforce::AuthenticationError if response.status != 200
15
+ raise Restforce::AuthenticationError, error_message(response) if response.status != 200
16
16
  @options[:instance_url] = response.body['instance_url']
17
17
  @options[:oauth_token] = response.body['access_token']
18
18
  end
@@ -0,0 +1,11 @@
1
+ module Restforce
2
+ class Middleware::Caching < FaradayMiddleware::Caching
3
+
4
+ # We don't want to cache requests for different clients, so append the
5
+ # oauth token to the cache key.
6
+ def cache_key(env)
7
+ super(env) + env[:request_headers][Restforce::Middleware::Authorization::AUTH_HEADER].gsub(/\s/, '')
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Restforce
2
+ class Middleware::Logger < Faraday::Response::Logger
3
+ def on_complete(env)
4
+ info('Status') { env[:status].to_s }
5
+ debug('response headers') { dump_headers env[:response_headers] }
6
+ debug('response body') { env[:body] }
7
+ end
8
+ end
9
+ end
@@ -5,6 +5,11 @@ module Restforce
5
5
  self.attributes.type
6
6
  end
7
7
 
8
+ # Public: Get the describe for this sobject type
9
+ def describe
10
+ @client.describe(sobject_type)
11
+ end
12
+
8
13
  # Public: Persist the attributes to Salesforce.
9
14
  #
10
15
  # Examples
@@ -1,3 +1,3 @@
1
1
  module Restforce
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -326,6 +326,13 @@ shared_examples_for 'methods' do
326
326
  subject { client.authenticate! }
327
327
  specify { expect { subject }.to_not raise_error }
328
328
  end
329
+
330
+ describe '.cache' do
331
+ let(:cache) { double('cache') }
332
+
333
+ subject { client.send :cache }
334
+ it { should eq cache }
335
+ end
329
336
  end
330
337
 
331
338
  describe 'with mashify middleware' do
@@ -26,7 +26,7 @@ describe Restforce::Middleware::Authentication::Password do
26
26
  stub_request(:post, "https://login.salesforce.com/services/oauth2/token").
27
27
  with(:body => "grant_type=password&client_id=client_id&client_secret=" \
28
28
  "client_secret&username=foo&password=barsecurity_token").
29
- to_return(:status => 400, :body => fixture(:auth_success_response))
29
+ to_return(:status => 400, :body => fixture(:auth_error_response))
30
30
  end
31
31
  end
32
32
 
@@ -24,7 +24,7 @@ describe Restforce::Middleware::Authentication::Token do
24
24
  stub_request(:post, "https://login.salesforce.com/services/oauth2/token").
25
25
  with(:body => "grant_type=refresh_token&refresh_token=refresh_token&" \
26
26
  "client_id=client_id&client_secret=client_secret").
27
- to_return(:status => 400, :body => fixture(:auth_success_response))
27
+ to_return(:status => 400, :body => fixture(:refresh_error_response))
28
28
  end
29
29
  end
30
30
  end
@@ -52,7 +52,7 @@ describe Restforce::Middleware::Authentication do
52
52
  end
53
53
 
54
54
  its(:handlers) { should include FaradayMiddleware::ParseJson, Faraday::Adapter::NetHttp }
55
- its(:handlers) { should_not include Faraday::Response::Logger }
55
+ its(:handlers) { should_not include Restforce::Middleware::Logger }
56
56
  end
57
57
 
58
58
  context 'with logging enabled' do
@@ -60,7 +60,7 @@ describe Restforce::Middleware::Authentication do
60
60
  Restforce.stub!(:log?).and_return(true)
61
61
  end
62
62
 
63
- its(:handlers) { should include FaradayMiddleware::ParseJson, Faraday::Response::Logger, Faraday::Adapter::NetHttp }
63
+ its(:handlers) { should include FaradayMiddleware::ParseJson, Restforce::Middleware::Logger, Faraday::Adapter::NetHttp }
64
64
  end
65
65
  end
66
66
  end
@@ -90,4 +90,17 @@ describe Restforce::SObject do
90
90
  specify { expect { subject }.to_not raise_error }
91
91
  end
92
92
  end
93
+
94
+ describe '.describe' do
95
+ before do
96
+ @request = stub_api_request 'sobject/Whizbang/describe', with: 'sobject/sobject_describe_success_response'
97
+ end
98
+
99
+ after do
100
+ @request.should have_been_requested
101
+ end
102
+
103
+ subject { sobject.describe }
104
+ it { should be_a Hash }
105
+ end
93
106
  end
@@ -7,6 +7,7 @@ shared_context 'basic client' do
7
7
  let(:security_token) { 'security_token' }
8
8
  let(:client_id) { 'client_id' }
9
9
  let(:client_secret) { 'client_secret' }
10
+ let(:cache) { nil }
10
11
 
11
12
  let(:base_options) do
12
13
  {
@@ -17,7 +18,8 @@ shared_context 'basic client' do
17
18
  :password => password,
18
19
  :security_token => security_token,
19
20
  :client_id => client_id,
20
- :client_secret => client_secret
21
+ :client_secret => client_secret,
22
+ :cache => cache
21
23
  }
22
24
  end
23
25
 
@@ -25,7 +25,7 @@ shared_examples_for 'authentication middleware' do
25
25
  it 'raises an exception' do
26
26
  expect {
27
27
  middleware.authenticate!
28
- }.to raise_error Restforce::AuthenticationError
28
+ }.to raise_error Restforce::AuthenticationError, /^invalid_grant: .*/
29
29
  end
30
30
  end
31
31
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restforce
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-11 00:00:00.000000000 Z
12
+ date: 2012-09-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -179,7 +179,9 @@ files:
179
179
  - lib/restforce/middleware/authentication/password.rb
180
180
  - lib/restforce/middleware/authentication/token.rb
181
181
  - lib/restforce/middleware/authorization.rb
182
+ - lib/restforce/middleware/caching.rb
182
183
  - lib/restforce/middleware/instance_url.rb
184
+ - lib/restforce/middleware/logger.rb
183
185
  - lib/restforce/middleware/mashify.rb
184
186
  - lib/restforce/middleware/multipart.rb
185
187
  - lib/restforce/middleware/raise_error.rb