restforce 1.5.3 → 2.0.0

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.

Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +60 -0
  3. data/.rubocop_todo.yml +117 -0
  4. data/.travis.yml +3 -5
  5. data/CHANGELOG.md +6 -0
  6. data/README.md +2 -0
  7. data/Rakefile +1 -1
  8. data/lib/restforce/abstract_client.rb +1 -1
  9. data/lib/restforce/attachment.rb +1 -3
  10. data/lib/restforce/concerns/api.rb +22 -17
  11. data/lib/restforce/concerns/authentication.rb +4 -3
  12. data/lib/restforce/concerns/base.rb +42 -31
  13. data/lib/restforce/concerns/caching.rb +1 -3
  14. data/lib/restforce/concerns/canvas.rb +0 -2
  15. data/lib/restforce/concerns/connection.rb +18 -12
  16. data/lib/restforce/concerns/picklists.rb +10 -10
  17. data/lib/restforce/concerns/streaming.rb +9 -4
  18. data/lib/restforce/concerns/verbs.rb +0 -2
  19. data/lib/restforce/config.rb +19 -13
  20. data/lib/restforce/data/client.rb +8 -1
  21. data/lib/restforce/mash.rb +6 -10
  22. data/lib/restforce/middleware.rb +3 -1
  23. data/lib/restforce/middleware/authentication.rb +21 -7
  24. data/lib/restforce/middleware/authentication/password.rb +5 -9
  25. data/lib/restforce/middleware/authentication/token.rb +4 -8
  26. data/lib/restforce/middleware/authorization.rb +0 -3
  27. data/lib/restforce/middleware/caching.rb +4 -4
  28. data/lib/restforce/middleware/instance_url.rb +3 -5
  29. data/lib/restforce/middleware/logger.rb +7 -7
  30. data/lib/restforce/middleware/mashify.rb +2 -3
  31. data/lib/restforce/middleware/multipart.rb +15 -8
  32. data/lib/restforce/middleware/raise_error.rb +2 -1
  33. data/lib/restforce/patches/parts.rb +2 -3
  34. data/lib/restforce/signed_request.rb +2 -2
  35. data/lib/restforce/sobject.rb +1 -3
  36. data/lib/restforce/tooling/client.rb +1 -3
  37. data/lib/restforce/upload_io.rb +1 -3
  38. data/lib/restforce/version.rb +1 -1
  39. data/restforce.gemspec +7 -4
  40. data/spec/integration/abstract_client_spec.rb +123 -75
  41. data/spec/integration/data/client_spec.rb +24 -12
  42. data/spec/spec_helper.rb +2 -2
  43. data/spec/support/client_integration.rb +23 -17
  44. data/spec/support/concerns.rb +2 -2
  45. data/spec/support/event_machine.rb +3 -3
  46. data/spec/support/fixture_helpers.rb +16 -12
  47. data/spec/support/middleware.rb +16 -8
  48. data/spec/unit/abstract_client_spec.rb +1 -1
  49. data/spec/unit/attachment_spec.rb +2 -1
  50. data/spec/unit/collection_spec.rb +13 -4
  51. data/spec/unit/concerns/api_spec.rb +15 -13
  52. data/spec/unit/concerns/authentication_spec.rb +20 -17
  53. data/spec/unit/concerns/base_spec.rb +2 -2
  54. data/spec/unit/concerns/caching_spec.rb +2 -2
  55. data/spec/unit/concerns/canvas_spec.rb +3 -3
  56. data/spec/unit/concerns/connection_spec.rb +6 -7
  57. data/spec/unit/concerns/streaming_spec.rb +8 -8
  58. data/spec/unit/config_spec.rb +6 -6
  59. data/spec/unit/data/client_spec.rb +1 -1
  60. data/spec/unit/mash_spec.rb +1 -1
  61. data/spec/unit/middleware/authentication/password_spec.rb +14 -12
  62. data/spec/unit/middleware/authentication/token_spec.rb +12 -10
  63. data/spec/unit/middleware/authentication_spec.rb +15 -11
  64. data/spec/unit/middleware/authorization_spec.rb +1 -1
  65. data/spec/unit/middleware/gzip_spec.rb +1 -1
  66. data/spec/unit/middleware/instance_url_spec.rb +2 -2
  67. data/spec/unit/middleware/mashify_spec.rb +2 -2
  68. data/spec/unit/middleware/raise_error_spec.rb +23 -7
  69. data/spec/unit/sobject_spec.rb +16 -9
  70. data/spec/unit/tooling/client_spec.rb +1 -1
  71. metadata +23 -5
@@ -1,20 +1,16 @@
1
1
  module Restforce
2
-
3
2
  # Authentication middleware used if username and password flow is used
4
3
  class Middleware::Authentication::Password < Restforce::Middleware::Authentication
5
-
6
4
  def params
7
- { :grant_type => 'password',
8
- :client_id => @options[:client_id],
9
- :client_secret => @options[:client_secret],
10
- :username => @options[:username],
11
- :password => password }
5
+ { grant_type: 'password',
6
+ client_id: @options[:client_id],
7
+ client_secret: @options[:client_secret],
8
+ username: @options[:username],
9
+ password: password }
12
10
  end
13
11
 
14
12
  def password
15
13
  "#{@options[:password]}#{@options[:security_token]}"
16
14
  end
17
-
18
15
  end
19
-
20
16
  end
@@ -1,15 +1,11 @@
1
1
  module Restforce
2
-
3
2
  # Authentication middleware used if oauth_token and refresh_token are set
4
3
  class Middleware::Authentication::Token < Restforce::Middleware::Authentication
5
-
6
4
  def params
7
- { :grant_type => 'refresh_token',
8
- :refresh_token => @options[:refresh_token],
9
- :client_id => @options[:client_id],
10
- :client_secret => @options[:client_secret] }
5
+ { grant_type: 'refresh_token',
6
+ refresh_token: @options[:refresh_token],
7
+ client_id: @options[:client_id],
8
+ client_secret: @options[:client_secret] }
11
9
  end
12
-
13
10
  end
14
-
15
11
  end
@@ -1,5 +1,4 @@
1
1
  module Restforce
2
-
3
2
  # Piece of middleware that simply injects the OAuth token into the request
4
3
  # headers.
5
4
  class Middleware::Authorization < Restforce::Middleware
@@ -13,7 +12,5 @@ module Restforce
13
12
  def token
14
13
  @options[:oauth_token]
15
14
  end
16
-
17
15
  end
18
-
19
16
  end
@@ -1,6 +1,5 @@
1
1
  module Restforce
2
2
  class Middleware::Caching < FaradayMiddleware::Caching
3
-
4
3
  def call(env)
5
4
  expire(cache_key(env)) unless use_cache?
6
5
  super
@@ -13,12 +12,13 @@ module Restforce
13
12
  # We don't want to cache requests for different clients, so append the
14
13
  # oauth token to the cache key.
15
14
  def cache_key(env)
16
- super(env) + env[:request_headers][Restforce::Middleware::Authorization::AUTH_HEADER].gsub(/\s/, '')
15
+ super(env) +
16
+ env[:request_headers][Restforce::Middleware::Authorization::AUTH_HEADER].
17
+ gsub(/\s/, '')
17
18
  end
18
19
 
19
20
  def use_cache?
20
- !@options.has_key?(:use_cache) || @options[:use_cache]
21
+ !@options.key?(:use_cache) || @options[:use_cache]
21
22
  end
22
-
23
23
  end
24
24
  end
@@ -1,18 +1,16 @@
1
1
  module Restforce
2
-
3
2
  # Middleware which asserts that the instance_url is always set
4
3
  class Middleware::InstanceURL < Restforce::Middleware
5
-
6
4
  def call(env)
7
5
  # If the connection url_prefix isn't set, we must not be authenticated.
8
- raise Restforce::UnauthorizedError, 'Connection prefix not set' unless url_prefix_set?
6
+ raise Restforce::UnauthorizedError,
7
+ 'Connection prefix not set' unless url_prefix_set?
8
+
9
9
  @app.call(env)
10
10
  end
11
11
 
12
12
  def url_prefix_set?
13
13
  !!(connection.url_prefix && connection.url_prefix.host)
14
14
  end
15
-
16
15
  end
17
-
18
16
  end
@@ -17,19 +17,19 @@ module Restforce
17
17
 
18
18
  def call(env)
19
19
  debug('request') do
20
- dump :url => env[:url].to_s,
21
- :method => env[:method],
22
- :headers => env[:request_headers],
23
- :body => env[:body]
20
+ dump url: env[:url].to_s,
21
+ method: env[:method],
22
+ headers: env[:request_headers],
23
+ body: env[:body]
24
24
  end
25
25
  super
26
26
  end
27
27
 
28
28
  def on_complete(env)
29
29
  debug('response') do
30
- dump :status => env[:status].to_s,
31
- :headers => env[:response_headers],
32
- :body => env[:body]
30
+ dump status: env[:status].to_s,
31
+ headers: env[:response_headers],
32
+ body: env[:body]
33
33
  end
34
34
  end
35
35
 
@@ -2,10 +2,9 @@ module Restforce
2
2
  # Middleware the converts sobject records from JSON into Restforce::SObject objects
3
3
  # and collections of records into Restforce::Collection objects.
4
4
  class Middleware::Mashify < Restforce::Middleware
5
-
6
5
  def call(env)
7
- @app.call(env).on_complete do |env|
8
- env[:body] = Restforce::Mash.build(env[:body], client)
6
+ @app.call(env).on_complete do |completed_env|
7
+ completed_env[:body] = Restforce::Mash.build(completed_env[:body], client)
9
8
  end
10
9
  end
11
10
  end
@@ -2,7 +2,7 @@ module Restforce
2
2
  class Middleware::Multipart < Faraday::Request::UrlEncoded
3
3
  self.mime_type = 'multipart/form-data'.freeze
4
4
  DEFAULT_BOUNDARY = "--boundary_string".freeze
5
- JSON_CONTENT_TYPE = {"Content-Type" => "application/json"}
5
+ JSON_CONTENT_TYPE = { "Content-Type" => "application/json" }
6
6
 
7
7
  def call(env)
8
8
  match_content_type(env) do |params|
@@ -16,8 +16,8 @@ module Restforce
16
16
 
17
17
  def process_request?(env)
18
18
  type = request_type(env)
19
- env[:body].respond_to?(:each_key) and !env[:body].empty? and (
20
- (type.empty? and has_multipart?(env[:body])) or
19
+ env[:body].respond_to?(:each_key) && !env[:body].empty? && (
20
+ (type.empty? && has_multipart?(env[:body])) ||
21
21
  type == self.class.mime_type
22
22
  )
23
23
  end
@@ -26,7 +26,7 @@ module Restforce
26
26
  # string is an enum in 1.8, returning list of itself
27
27
  if obj.respond_to?(:each) && !obj.is_a?(String)
28
28
  (obj.respond_to?(:values) ? obj.values : obj).each do |val|
29
- return true if (val.respond_to?(:content_type) || has_multipart?(val))
29
+ return true if val.respond_to?(:content_type) || has_multipart?(val)
30
30
  end
31
31
  end
32
32
  false
@@ -37,18 +37,25 @@ module Restforce
37
37
  parts = []
38
38
 
39
39
  # Fields
40
- parts << Faraday::Parts::Part.new(boundary, 'entity_content', params.reject { |k,v| v.respond_to? :content_type }.to_json, JSON_CONTENT_TYPE)
40
+ parts << Faraday::Parts::Part.new(
41
+ boundary,
42
+ 'entity_content',
43
+ params.reject { |k, v| v.respond_to? :content_type }.to_json,
44
+ JSON_CONTENT_TYPE
45
+ )
41
46
 
42
47
  # Files
43
- params.each do |k,v|
44
- parts << Faraday::Parts::Part.new(boundary, k.to_s, v) if v.respond_to? :content_type
48
+ params.each do |k, v|
49
+ parts << Faraday::Parts::Part.new(boundary,
50
+ k.to_s,
51
+ v) if v.respond_to? :content_type
45
52
  end
46
53
 
47
54
  parts << Faraday::Parts::EpiloguePart.new(boundary)
48
55
 
49
56
  body = Faraday::CompositeReadIO.new(parts)
50
57
  env[:request_headers]['Content-Length'] = body.length.to_s
51
- return body
58
+ body
52
59
  end
53
60
  end
54
61
  end
@@ -8,7 +8,8 @@ module Restforce
8
8
  when 401
9
9
  raise Restforce::UnauthorizedError, message
10
10
  when 413
11
- raise Faraday::Error::ClientError.new("HTTP 413 - Request Entity Too Large", env[:response])
11
+ raise Faraday::Error::ClientError.new("HTTP 413 - Request Entity Too Large",
12
+ env[:response])
12
13
  when 400...600
13
14
  raise Faraday::Error::ClientError.new(message, env[:response])
14
15
  end
@@ -1,6 +1,5 @@
1
1
  module Faraday
2
2
  module Parts
3
-
4
3
  module Part
5
4
  def self.new(boundary, name, value, headers = {})
6
5
  headers ||= {}
@@ -21,8 +20,8 @@ module Faraday
21
20
  def build_part(boundary, name, value, headers = {})
22
21
  part = ''
23
22
  part << "--#{boundary}\r\n"
24
- part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n"
25
- part << "Content-Type: #{headers["Content-Type"]}\r\n" if headers["Content-Type"]
23
+ part << "Content-Disposition: form-data; name=\"#{name}\"\r\n"
24
+ part << "Content-Type: #{headers['Content-Type']}\r\n" if headers["Content-Type"]
26
25
  part << "\r\n"
27
26
  part << "#{value}\r\n"
28
27
  end
@@ -28,7 +28,8 @@ module Restforce
28
28
  JSON.parse(Base64.decode64(payload))
29
29
  end
30
30
 
31
- private
31
+ private
32
+
32
33
  attr_reader :client_secret, :signature, :payload
33
34
 
34
35
  def split_components(signed_request)
@@ -51,6 +52,5 @@ module Restforce
51
52
  OpenSSL::Digest
52
53
  end
53
54
  end
54
-
55
55
  end
56
56
  end
@@ -1,6 +1,5 @@
1
1
  module Restforce
2
2
  class SObject < Restforce::Mash
3
-
4
3
  def sobject_type
5
4
  self.attributes['type']
6
5
  end
@@ -58,12 +57,11 @@ module Restforce
58
57
  self.Id
59
58
  end
60
59
 
61
- private
60
+ private
62
61
 
63
62
  def ensure_id
64
63
  return true if self.Id?
65
64
  raise ArgumentError, 'You need to query the Id for the record first.'
66
65
  end
67
-
68
66
  end
69
67
  end
@@ -1,13 +1,11 @@
1
1
  module Restforce
2
2
  module Tooling
3
3
  class Client < AbstractClient
4
-
5
4
  private
6
5
 
7
6
  def api_path(path)
8
7
  super("tooling/#{path}")
9
8
  end
10
-
11
9
  end
12
10
  end
13
- end
11
+ end
@@ -4,6 +4,4 @@ module Restforce
4
4
  UploadIO = Faraday::UploadIO
5
5
  end
6
6
 
7
- unless Parts::Part.method(:new).arity.abs == 4
8
- require 'restforce/patches/parts'
9
- end
7
+ require 'restforce/patches/parts' unless Parts::Part.method(:new).arity.abs == 4
@@ -1,3 +1,3 @@
1
1
  module Restforce
2
- VERSION = '1.5.3'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -2,10 +2,10 @@
2
2
  require File.expand_path('../lib/restforce/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
- gem.authors = ["Eric J. Holmes"]
6
- gem.email = ["eric@ejholmes.net"]
7
- gem.description = %q{A lightweight ruby client for the Salesforce REST api.}
8
- gem.summary = %q{A lightweight ruby client for the Salesforce REST api.}
5
+ gem.authors = ["Eric J. Holmes", "Tim Rogers"]
6
+ gem.email = ["eric@ejholmes.net", "tim@gocardless.com"]
7
+ gem.description = %q{A lightweight ruby client for the Salesforce REST API.}
8
+ gem.summary = %q{A lightweight ruby client for the Salesforce REST API.}
9
9
  gem.homepage = "https://github.com/ejholmes/restforce"
10
10
 
11
11
  gem.files = `git ls-files`.split($\)
@@ -15,6 +15,8 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = Restforce::VERSION
17
17
 
18
+ gem.required_ruby_version = '>= 1.9.3'
19
+
18
20
  gem.add_dependency 'faraday', '~> 0.9.0'
19
21
  gem.add_dependency 'faraday_middleware', '>= 0.8.8'
20
22
  gem.add_dependency 'json', ['>= 1.7.5', '< 1.9.0']
@@ -23,5 +25,6 @@ Gem::Specification.new do |gem|
23
25
  gem.add_development_dependency 'rspec', '~> 2.14.0'
24
26
  gem.add_development_dependency 'webmock', '~> 1.13.0'
25
27
  gem.add_development_dependency 'simplecov', '~> 0.7.1'
28
+ gem.add_development_dependency 'rubocop', '~> 0.31.0'
26
29
  gem.add_development_dependency 'faye' unless RUBY_PLATFORM == 'java'
27
30
  end
@@ -1,9 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  shared_examples_for Restforce::AbstractClient do
4
-
5
4
  describe '.list_sobjects' do
6
- requests :sobjects, :fixture => 'sobject/describe_sobjects_success_response'
5
+ requests :sobjects, fixture: 'sobject/describe_sobjects_success_response'
7
6
 
8
7
  subject { client.list_sobjects }
9
8
  it { should be_an Array }
@@ -12,14 +11,15 @@ shared_examples_for Restforce::AbstractClient do
12
11
 
13
12
  describe '.describe' do
14
13
  context 'with no arguments' do
15
- requests :sobjects, :fixture => 'sobject/describe_sobjects_success_response'
14
+ requests :sobjects, fixture: 'sobject/describe_sobjects_success_response'
16
15
 
17
16
  subject { client.describe }
18
17
  it { should be_an Array }
19
18
  end
20
19
 
21
20
  context 'with an argument' do
22
- requests 'sobjects/Whizbang/describe', :fixture => 'sobject/sobject_describe_success_response'
21
+ requests 'sobjects/Whizbang/describe',
22
+ fixture: 'sobject/sobject_describe_success_response'
23
23
 
24
24
  subject { client.describe('Whizbang') }
25
25
  its(['name']) { should eq 'Whizbang' }
@@ -27,14 +27,15 @@ shared_examples_for Restforce::AbstractClient do
27
27
  end
28
28
 
29
29
  describe '.query' do
30
- requests 'query\?q=SELECT%20some,%20fields%20FROM%20object', :fixture => 'sobject/query_success_response'
30
+ requests 'query\?q=SELECT%20some,%20fields%20FROM%20object',
31
+ fixture: 'sobject/query_success_response'
31
32
 
32
33
  subject { client.query('SELECT some, fields FROM object') }
33
34
  it { should be_an Enumerable }
34
35
  end
35
36
 
36
37
  describe '.search' do
37
- requests 'search\?q=FIND%20%7Bbar%7D', :fixture => 'sobject/search_success_response'
38
+ requests 'search\?q=FIND%20%7Bbar%7D', fixture: 'sobject/search_success_response'
38
39
 
39
40
  subject { client.search('FIND {bar}') }
40
41
  it { should be_an Array }
@@ -42,7 +43,8 @@ shared_examples_for Restforce::AbstractClient do
42
43
  end
43
44
 
44
45
  describe '.org_id' do
45
- requests 'query\?q=select%20id%20from%20Organization', :fixture => 'sobject/org_query_response'
46
+ requests 'query\?q=select%20id%20from%20Organization',
47
+ fixture: 'sobject/org_query_response'
46
48
 
47
49
  subject { client.org_id }
48
50
  it { should eq '00Dx0000000BV7z' }
@@ -51,21 +53,30 @@ shared_examples_for Restforce::AbstractClient do
51
53
  describe '.create' do
52
54
  context 'without multipart' do
53
55
  requests 'sobjects/Account',
54
- :method => :post,
55
- :with_body => "{\"Name\":\"Foobar\"}",
56
- :fixture => 'sobject/create_success_response'
56
+ method: :post,
57
+ with_body: "{\"Name\":\"Foobar\"}",
58
+ fixture: 'sobject/create_success_response'
57
59
 
58
- subject { client.create('Account', :Name => 'Foobar') }
60
+ subject { client.create('Account', Name: 'Foobar') }
59
61
  it { should eq 'some_id' }
60
62
  end
61
63
 
62
64
  context 'with multipart' do
65
+ # rubocop:disable Metrics/LineLength
63
66
  requests 'sobjects/Account',
64
- :method => :post,
65
- :with_body => %r(----boundary_string\r\nContent-Disposition: form-data; name=\"entity_content\"\r\nContent-Type: application/json\r\n\r\n{\"Name\":\"Foobar\"}\r\n----boundary_string\r\nContent-Disposition: form-data; name=\"Blob\"; filename=\"blob.jpg\"\r\nContent-Length: 42171\r\nContent-Type: image/jpeg\r\nContent-Transfer-Encoding: binary),
66
- :fixture => 'sobject/create_success_response'
67
+ method: :post,
68
+ with_body: %r(----boundary_string\r\nContent-Disposition: form-data; name=\"entity_content\"\r\nContent-Type: application/json\r\n\r\n{\"Name\":\"Foobar\"}\r\n----boundary_string\r\nContent-Disposition: form-data; name=\"Blob\"; filename=\"blob.jpg\"\r\nContent-Length: 42171\r\nContent-Type: image/jpeg\r\nContent-Transfer-Encoding: binary),
69
+ fixture: 'sobject/create_success_response'
70
+ # rubocop:enable Metrics/LineLength
71
+
72
+ subject do
73
+ client.create('Account', Name: 'Foobar',
74
+ Blob: Restforce::UploadIO.new(
75
+ File.expand_path('../../fixtures/blob.jpg', __FILE__),
76
+ 'image/jpeg'
77
+ ))
78
+ end
67
79
 
68
- subject { client.create('Account', :Name => 'Foobar', :Blob => Restforce::UploadIO.new(File.expand_path('../../fixtures/blob.jpg', __FILE__), 'image/jpeg')) }
69
80
  it { should eq 'some_id' }
70
81
  end
71
82
  end
@@ -73,41 +84,49 @@ shared_examples_for Restforce::AbstractClient do
73
84
  describe '.update!' do
74
85
  context 'with invalid Id' do
75
86
  requests 'sobjects/Account/001D000000INjVe',
76
- :method => :patch,
77
- :with_body => "{\"Name\":\"Foobar\"}",
78
- :status => 404,
79
- :fixture => 'sobject/delete_error_response'
87
+ method: :patch,
88
+ with_body: "{\"Name\":\"Foobar\"}",
89
+ status: 404,
90
+ fixture: 'sobject/delete_error_response'
91
+
92
+ subject do
93
+ lambda do
94
+ client.update!('Account', Id: '001D000000INjVe', Name: 'Foobar')
95
+ end
96
+ end
80
97
 
81
- subject { lambda { client.update!('Account', :Id => '001D000000INjVe', :Name => 'Foobar') } }
82
98
  it { should raise_error Faraday::Error::ResourceNotFound }
83
99
  end
84
100
  end
85
101
 
86
102
  describe '.update' do
87
103
  context 'with missing Id' do
88
- subject { lambda { client.update('Account', :Name => 'Foobar') } }
104
+ subject { lambda { client.update('Account', Name: 'Foobar') } }
89
105
  it { should raise_error ArgumentError, 'Id field missing from attrs.' }
90
106
  end
91
107
 
92
108
  context 'with invalid Id' do
93
109
  requests 'sobjects/Account/001D000000INjVe',
94
- :method => :patch,
95
- :with_body => "{\"Name\":\"Foobar\"}",
96
- :status => 404,
97
- :fixture => 'sobject/delete_error_response'
110
+ method: :patch,
111
+ with_body: "{\"Name\":\"Foobar\"}",
112
+ status: 404,
113
+ fixture: 'sobject/delete_error_response'
98
114
 
99
- subject { client.update('Account', :Id => '001D000000INjVe', :Name => 'Foobar') }
115
+ subject { client.update('Account', Id: '001D000000INjVe', Name: 'Foobar') }
100
116
  it { should be_false }
101
117
  end
102
118
 
103
119
  context 'with success' do
104
120
  requests 'sobjects/Account/001D000000INjVe',
105
- :method => :patch,
106
- :with_body => "{\"Name\":\"Foobar\"}"
121
+ method: :patch,
122
+ with_body: "{\"Name\":\"Foobar\"}"
107
123
 
108
124
  [:Id, :id, 'Id', 'id'].each do |key|
109
125
  context "with #{key.inspect} as the key" do
110
- subject { client.update('Account', key => '001D000000INjVe', :Name => 'Foobar') }
126
+ subject do
127
+ client.update('Account', key => '001D000000INjVe', :Name => 'Foobar')
128
+ end
129
+
111
130
  it { should be_true }
112
131
  end
113
132
  end
@@ -117,29 +136,41 @@ shared_examples_for Restforce::AbstractClient do
117
136
  describe '.upsert!' do
118
137
  context 'when updated' do
119
138
  requests 'sobjects/Account/External__c/foobar',
120
- :method => :patch,
121
- :with_body => "{\"Name\":\"Foobar\"}"
139
+ method: :patch,
140
+ with_body: "{\"Name\":\"Foobar\"}"
122
141
 
123
142
  context 'with symbol external Id key' do
124
- subject { client.upsert!('Account', 'External__c', :External__c => 'foobar', :Name => 'Foobar') }
143
+ subject do
144
+ client.upsert!('Account', 'External__c', External__c: 'foobar',
145
+ Name: 'Foobar')
146
+ end
147
+
125
148
  it { should be_true }
126
149
  end
127
150
 
128
151
  context 'with string external Id key' do
129
- subject { client.upsert!('Account', 'External__c', 'External__c' => 'foobar', 'Name' => 'Foobar') }
152
+ subject do
153
+ client.upsert!('Account', 'External__c', 'External__c' => 'foobar',
154
+ 'Name' => 'Foobar')
155
+ end
156
+
130
157
  it { should be_true }
131
158
  end
132
159
  end
133
160
 
134
161
  context 'when created' do
135
162
  requests 'sobjects/Account/External__c/foobar',
136
- :method => :patch,
137
- :with_body => "{\"Name\":\"Foobar\"}",
138
- :fixture => 'sobject/upsert_created_success_response'
163
+ method: :patch,
164
+ with_body: "{\"Name\":\"Foobar\"}",
165
+ fixture: 'sobject/upsert_created_success_response'
139
166
 
140
167
  [:External__c, 'External__c', :external__c, 'external__c'].each do |key|
141
168
  context "with #{key.inspect} as the external id" do
142
- subject { client.upsert!('Account', 'External__c', key => 'foobar', :Name => 'Foobar') }
169
+ subject do
170
+ client.upsert!('Account', 'External__c', key => 'foobar',
171
+ :Name => 'Foobar')
172
+ end
173
+
143
174
  it { should eq 'foo' }
144
175
  end
145
176
  end
@@ -151,16 +182,16 @@ shared_examples_for Restforce::AbstractClient do
151
182
 
152
183
  context 'with invalid Id' do
153
184
  requests 'sobjects/Account/001D000000INjVe',
154
- :fixture => 'sobject/delete_error_response',
155
- :method => :delete,
156
- :status => 404
185
+ fixture: 'sobject/delete_error_response',
186
+ method: :delete,
187
+ status: 404
157
188
 
158
189
  subject { lambda { destroy! } }
159
190
  it { should raise_error Faraday::Error::ResourceNotFound }
160
191
  end
161
192
 
162
193
  context 'with success' do
163
- requests 'sobjects/Account/001D000000INjVe', :method => :delete
194
+ requests 'sobjects/Account/001D000000INjVe', method: :delete
164
195
 
165
196
  it { should be_true }
166
197
  end
@@ -171,15 +202,15 @@ shared_examples_for Restforce::AbstractClient do
171
202
 
172
203
  context 'with invalid Id' do
173
204
  requests 'sobjects/Account/001D000000INjVe',
174
- :fixture => 'sobject/delete_error_response',
175
- :method => :delete,
176
- :status => 404
205
+ fixture: 'sobject/delete_error_response',
206
+ method: :delete,
207
+ status: 404
177
208
 
178
209
  it { should be_false }
179
210
  end
180
211
 
181
212
  context 'with success' do
182
- requests 'sobjects/Account/001D000000INjVe', :method => :delete
213
+ requests 'sobjects/Account/001D000000INjVe', method: :delete
183
214
 
184
215
  it { should be_true }
185
216
  end
@@ -188,7 +219,7 @@ shared_examples_for Restforce::AbstractClient do
188
219
  describe '.find' do
189
220
  context 'with no external id passed' do
190
221
  requests 'sobjects/Account/001D000000INjVe',
191
- :fixture => 'sobject/sobject_find_success_response'
222
+ fixture: 'sobject/sobject_find_success_response'
192
223
 
193
224
  subject { client.find('Account', '001D000000INjVe') }
194
225
  it { should be_a Hash }
@@ -196,7 +227,7 @@ shared_examples_for Restforce::AbstractClient do
196
227
 
197
228
  context 'when an external id is passed' do
198
229
  requests 'sobjects/Account/External_Field__c/1234',
199
- :fixture => 'sobject/sobject_find_success_response'
230
+ fixture: 'sobject/sobject_find_success_response'
200
231
 
201
232
  subject { client.find('Account', '1234', 'External_Field__c') }
202
233
  it { should be_a Hash }
@@ -207,14 +238,14 @@ shared_examples_for Restforce::AbstractClient do
207
238
  context 'when no external id is specified' do
208
239
  context 'when no select list is specified' do
209
240
  requests 'sobjects/Account/1234',
210
- :fixture => 'sobject/sobject_select_success_response'
241
+ fixture: 'sobject/sobject_select_success_response'
211
242
 
212
243
  subject { client.select('Account', '1234', nil, nil) }
213
244
  it { should be_a Hash }
214
245
  end
215
246
  context 'when select list is specified' do
216
247
  requests 'sobjects/Account/1234\?fields=External_Field__c',
217
- :fixture => 'sobject/sobject_select_success_response'
248
+ fixture: 'sobject/sobject_select_success_response'
218
249
 
219
250
  subject { client.select('Account', '1234', ['External_Field__c']) }
220
251
  it { should be_a Hash }
@@ -224,7 +255,7 @@ shared_examples_for Restforce::AbstractClient do
224
255
  context 'when an external id is specified' do
225
256
  context 'when no select list is specified' do
226
257
  requests 'sobjects/Account/External_Field__c/1234',
227
- :fixture => 'sobject/sobject_select_success_response'
258
+ fixture: 'sobject/sobject_select_success_response'
228
259
 
229
260
  subject { client.select('Account', '1234', nil, 'External_Field__c') }
230
261
  it { should be_a Hash }
@@ -232,9 +263,12 @@ shared_examples_for Restforce::AbstractClient do
232
263
 
233
264
  context 'when select list is specified' do
234
265
  requests 'sobjects/Account/External_Field__c/1234\?fields=External_Field__c',
235
- :fixture => 'sobject/sobject_select_success_response'
266
+ fixture: 'sobject/sobject_select_success_response'
267
+
268
+ subject do
269
+ client.select('Account', '1234', ['External_Field__c'], 'External_Field__c')
270
+ end
236
271
 
237
- subject { client.select('Account', '1234', ['External_Field__c'], 'External_Field__c') }
238
272
  it { should be_a Hash }
239
273
  end
240
274
  end
@@ -245,9 +279,11 @@ shared_examples_for Restforce::AbstractClient do
245
279
 
246
280
  context 'when successful' do
247
281
  before do
248
- @request = stub_login_request(:with_body => "grant_type=password&client_id=client_id&client_secret=" \
249
- "client_secret&username=foo&password=barsecurity_token").
250
- to_return(:status => 200, :body => fixture(:auth_success_response))
282
+ @request = stub_login_request(
283
+ with_body: "grant_type=password&client_id=client_id" \
284
+ "&client_secret=client_secret&username=foo" \
285
+ "&password=barsecurity_token"
286
+ ).to_return(status: 200, body: fixture(:auth_success_response))
251
287
  end
252
288
 
253
289
  after do
@@ -262,14 +298,16 @@ shared_examples_for Restforce::AbstractClient do
262
298
  client.stub(:authentication_middleware).and_return(nil)
263
299
  end
264
300
 
265
- subject { lambda { authenticate! } }
266
- it { should raise_error Restforce::AuthenticationError, 'No authentication middleware present'}
301
+ it "raises an error" do
302
+ expect { authenticate! }.to raise_error Restforce::AuthenticationError,
303
+ 'No authentication middleware present'
304
+ end
267
305
  end
268
306
  end
269
307
 
270
308
  describe '.without_caching' do
271
309
  requests 'query\?q=SELECT%20some,%20fields%20FROM%20object',
272
- :fixture => 'sobject/query_success_response'
310
+ fixture: 'sobject/query_success_response'
273
311
 
274
312
  before do
275
313
  cache.should_receive(:delete).and_call_original
@@ -284,12 +322,17 @@ shared_examples_for Restforce::AbstractClient do
284
322
  describe 'authentication retries' do
285
323
  context 'when retries reaches 0' do
286
324
  before do
287
- @auth_request = stub_api_request('query\?q=SELECT%20some,%20fields%20FROM%20object',
288
- :status => 401,
289
- :fixture => 'expired_session_response')
290
- @query_request = stub_login_request(:with_body => "grant_type=password&client_id=client_id&client_secret=" \
291
- "client_secret&username=foo&password=barsecurity_token").
292
- to_return(:status => 200, :body => fixture(:auth_success_response))
325
+ @auth_request = stub_api_request(
326
+ 'query\?q=SELECT%20some,%20fields%20FROM%20object',
327
+ status: 401,
328
+ fixture: 'expired_session_response'
329
+ )
330
+
331
+ @query_request = stub_login_request(
332
+ with_body: "grant_type=password&client_id=client_id" \
333
+ "&client_secret=client_secret&username=foo&" \
334
+ "password=barsecurity_token"
335
+ ).to_return(status: 200, body: fixture(:auth_success_response))
293
336
  end
294
337
 
295
338
  subject { lambda { client.query('SELECT some, fields FROM object') } }
@@ -302,13 +345,18 @@ shared_examples_for Restforce::AbstractClient do
302
345
 
303
346
  before do
304
347
  @query = stub_api_request('query\?q=SELECT%20some,%20fields%20FROM%20object').
305
- with(:headers => { 'Authorization' => "OAuth #{oauth_token}" }).
306
- to_return(:status => 401, :body => fixture('expired_session_response'), :headers => { 'Content-Type' => 'application/json' }).then.
307
- to_return(:status => 200, :body => fixture('sobject/query_success_response'), :headers => { 'Content-Type' => 'application/json' })
308
-
309
- @login = stub_login_request(:with_body => "grant_type=password&client_id=client_id&client_secret=" \
310
- "client_secret&username=foo&password=barsecurity_token").
311
- to_return(:status => 200, :body => fixture(:auth_success_response))
348
+ with(headers: { 'Authorization' => "OAuth #{oauth_token}" }).
349
+ to_return(status: 401,
350
+ body: fixture('expired_session_response'),
351
+ headers: { 'Content-Type' => 'application/json' }).then.
352
+ to_return(status: 200,
353
+ body: fixture('sobject/query_success_response'),
354
+ headers: { 'Content-Type' => 'application/json' })
355
+
356
+ @login = stub_login_request(
357
+ with_body: "grant_type=password&client_id=client_id&client_secret=" \
358
+ "client_secret&username=foo&password=barsecurity_token"
359
+ ).to_return(status: 200, body: fixture(:auth_success_response))
312
360
  end
313
361
 
314
362
  after do
@@ -329,16 +377,16 @@ describe Restforce::AbstractClient do
329
377
  context 'with pagination' do
330
378
  subject { client.query('SELECT some, fields FROM object').next_page }
331
379
 
332
- requests 'query\?q', :fixture => 'sobject/query_paginated_first_page_response'
333
- requests 'query/01gD', :fixture => 'sobject/query_paginated_last_page_response'
380
+ requests 'query\?q', fixture: 'sobject/query_paginated_first_page_response'
381
+ requests 'query/01gD', fixture: 'sobject/query_paginated_last_page_response'
334
382
 
335
383
  it { should be_a Restforce::Collection }
336
- its('first.Text_Label') { should eq 'Last Page'}
384
+ its('first.Text_Label') { should eq 'Last Page' }
337
385
  end
338
386
  end
339
387
  end
340
388
 
341
- describe 'without mashify', :mashify => false do
389
+ describe 'without mashify', mashify: false do
342
390
  it_behaves_like Restforce::AbstractClient
343
391
  end
344
392
  end