restforce 5.0.5 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +9 -9
- data/.github/dependabot.yml +19 -0
- data/.rubocop.yml +2 -2
- data/CHANGELOG.md +23 -0
- data/Gemfile +10 -6
- data/README.md +53 -4
- data/lib/restforce/abstract_client.rb +1 -0
- data/lib/restforce/collection.rb +15 -1
- data/lib/restforce/concerns/api.rb +1 -1
- data/lib/restforce/concerns/base.rb +2 -2
- data/lib/restforce/concerns/composite_api.rb +104 -0
- data/lib/restforce/concerns/picklists.rb +1 -1
- data/lib/restforce/error_code.rb +27 -9
- data/lib/restforce/middleware/logger.rb +5 -5
- data/lib/restforce/version.rb +1 -1
- data/lib/restforce.rb +2 -0
- data/restforce.gemspec +2 -12
- data/spec/integration/abstract_client_spec.rb +25 -28
- data/spec/integration/data/client_spec.rb +6 -2
- data/spec/spec_helper.rb +10 -0
- data/spec/support/client_integration.rb +7 -7
- data/spec/support/concerns.rb +1 -1
- data/spec/support/middleware.rb +1 -2
- data/spec/unit/collection_spec.rb +4 -4
- data/spec/unit/concerns/api_spec.rb +11 -11
- data/spec/unit/concerns/authentication_spec.rb +6 -6
- data/spec/unit/concerns/composite_api_spec.rb +143 -0
- data/spec/unit/concerns/streaming_spec.rb +3 -3
- data/spec/unit/config_spec.rb +1 -1
- data/spec/unit/middleware/authentication/jwt_bearer_spec.rb +4 -4
- data/spec/unit/middleware/authentication/password_spec.rb +2 -2
- data/spec/unit/middleware/authentication/token_spec.rb +2 -2
- data/spec/unit/middleware/gzip_spec.rb +2 -2
- data/spec/unit/middleware/raise_error_spec.rb +20 -10
- metadata +12 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f30c54c95fc530b6278faf751728b2793971c8aa0e43862f6719753a1d62d4fa
|
4
|
+
data.tar.gz: c7ac3a654170e2cb883325b12f4e6315d0c0423f9673142c93c87cf5de2003b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a731ebfe6e755b66479f8e85434a017d50a81c084f048e1454f3714bb047c36f8362976c904a91890b8f62099a3238689fe93f200468670b8f4dafc51cb5aa5
|
7
|
+
data.tar.gz: f5e8cd87fc4eccd486828627dfa1c769107e5869f7cf60088d5c7ee2cde2207d9bf33794a4f1639b98cfccfee54734d583dcbdbea8d841442a7086ff00b9e315
|
data/.circleci/config.yml
CHANGED
@@ -34,23 +34,23 @@ references:
|
|
34
34
|
destination: test-results
|
35
35
|
|
36
36
|
jobs:
|
37
|
-
build-
|
37
|
+
build-ruby30:
|
38
38
|
docker:
|
39
|
-
- image: circleci/ruby:
|
39
|
+
- image: circleci/ruby:3.0
|
40
40
|
steps: *steps
|
41
|
-
build-
|
41
|
+
build-ruby27:
|
42
42
|
docker:
|
43
|
-
- image: circleci/ruby:2.
|
43
|
+
- image: circleci/ruby:2.7
|
44
44
|
steps: *steps
|
45
|
-
build-
|
45
|
+
build-ruby26:
|
46
46
|
docker:
|
47
|
-
- image: circleci/ruby:2.
|
47
|
+
- image: circleci/ruby:2.6
|
48
48
|
steps: *steps
|
49
49
|
|
50
50
|
workflows:
|
51
51
|
version: 2
|
52
52
|
tests:
|
53
53
|
jobs:
|
54
|
-
- build-
|
55
|
-
- build-
|
56
|
-
- build-
|
54
|
+
- build-ruby30
|
55
|
+
- build-ruby27
|
56
|
+
- build-ruby26
|
@@ -0,0 +1,19 @@
|
|
1
|
+
version: 2
|
2
|
+
updates:
|
3
|
+
- package-ecosystem: bundler
|
4
|
+
directory: "/"
|
5
|
+
schedule:
|
6
|
+
interval: daily
|
7
|
+
open-pull-requests-limit: 10
|
8
|
+
ignore:
|
9
|
+
- dependency-name: rubocop
|
10
|
+
versions:
|
11
|
+
- 1.10.0
|
12
|
+
- 1.11.0
|
13
|
+
- 1.12.0
|
14
|
+
- 1.12.1
|
15
|
+
- 1.9.0
|
16
|
+
- dependency-name: webmock
|
17
|
+
versions:
|
18
|
+
- 3.12.0
|
19
|
+
- 3.12.1
|
data/.rubocop.yml
CHANGED
@@ -8,7 +8,7 @@ AllCops:
|
|
8
8
|
- .*/**/*
|
9
9
|
- vendor/**/*
|
10
10
|
NewCops: enable
|
11
|
-
TargetRubyVersion: 2.
|
11
|
+
TargetRubyVersion: 2.6
|
12
12
|
|
13
13
|
# Limit lines to 90 characters.
|
14
14
|
Layout/LineLength:
|
@@ -71,4 +71,4 @@ Naming/FileName:
|
|
71
71
|
- Guardfile
|
72
72
|
|
73
73
|
Lint/UriEscapeUnescape:
|
74
|
-
Enabled: false
|
74
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## 5.2.0 (Oct 15, 2021)
|
2
|
+
|
3
|
+
* Add support for Salesforce's Composite API and Composite Batch API (@meenie, @amacdougall)
|
4
|
+
* Improve the performance of counting numbers of query results with `Restforce::Collection#count`, avoiding unnecessary API requests (@jhass)
|
5
|
+
|
6
|
+
## 5.1.1 (Oct 13, 2021)
|
7
|
+
|
8
|
+
* Handle the `INVALID_REPLICATION_DATE` error returned by Salesforce (@michaelwnyc)
|
9
|
+
* Handle the `BIG_OBJECT_UNSUPPORTED_OPERATION` error returned by Salesforce (@remon)
|
10
|
+
|
11
|
+
## 5.1.0 (Aug 26, 2021)
|
12
|
+
|
13
|
+
* Add official support for Ruby 3.0 (@timrogers)
|
14
|
+
* Drop support for Ruby 2.5, which has reached end-of-life (@timrogers)
|
15
|
+
* Handle the `QUERY_TIMEOUT` error returned by Salesforce (@timrogers)
|
16
|
+
* Remove unnecessary development dependencies for the gem, which can just be in the project's `Gemfile` (@timrogers)
|
17
|
+
|
18
|
+
## 5.0.6 (Jun 17, 2021)
|
19
|
+
|
20
|
+
* Handle the `API_DISABLED_FOR_ORG` error returned by Salesforce (@cmac)
|
21
|
+
* Handle the `METHOD_NOT_ALLOWED` error returned by Salesforce (@timrogers)
|
22
|
+
* Handle the `APEX_ERROR` error returned by Salesforce (@timrogers)
|
23
|
+
|
1
24
|
## 5.0.5 (Feb 17, 2021)
|
2
25
|
|
3
26
|
* Handle the `CANNOT_EXECUTE_FLOW_TRIGGER` error returned by Salesforce (@almusavi, @timrogers)
|
data/Gemfile
CHANGED
@@ -3,11 +3,15 @@
|
|
3
3
|
source 'https://rubygems.org'
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
gem 'faye' unless RUBY_PLATFORM == 'java'
|
7
|
+
gem 'guard-rspec'
|
8
|
+
gem 'guard-rubocop'
|
6
9
|
gem 'jruby-openssl', platforms: :jruby
|
7
|
-
gem 'jwt'
|
8
10
|
gem 'rake'
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
gem 'rspec', '~> 3.10.0'
|
12
|
+
gem 'rspec-collection_matchers', '~> 1.2.0'
|
13
|
+
gem 'rspec-its', '~> 1.3.0'
|
14
|
+
gem 'rspec_junit_formatter', '~> 0.4.1'
|
15
|
+
gem 'rubocop', '~> 1.22.1'
|
16
|
+
gem 'simplecov', '~> 0.21.2'
|
17
|
+
gem 'webmock', '~> 3.14.0'
|
data/README.md
CHANGED
@@ -12,6 +12,8 @@ Features include:
|
|
12
12
|
* Support for parent-to-child relationships.
|
13
13
|
* Support for aggregate queries.
|
14
14
|
* Support for the [Streaming API](#streaming)
|
15
|
+
* Support for the [Composite API](#composite-api)
|
16
|
+
* Support for the [Composite Batch API](#composite-batch-api)
|
15
17
|
* Support for the GetUpdated API
|
16
18
|
* Support for blob data types.
|
17
19
|
* Support for GZIP compression.
|
@@ -25,7 +27,7 @@ Features include:
|
|
25
27
|
|
26
28
|
Add this line to your application's Gemfile:
|
27
29
|
|
28
|
-
gem 'restforce', '~> 5.0
|
30
|
+
gem 'restforce', '~> 5.2.0'
|
29
31
|
|
30
32
|
And then execute:
|
31
33
|
|
@@ -35,8 +37,9 @@ Or install it yourself as:
|
|
35
37
|
|
36
38
|
$ gem install restforce
|
37
39
|
|
38
|
-
__As of version 5.
|
40
|
+
__As of version 5.1.0, this gem is only compatible with Ruby 2.6.0 and later.__ If you're using an earlier Ruby version:
|
39
41
|
|
42
|
+
* for Ruby 2.5, use version 5.0.6 or earlier
|
40
43
|
* for Ruby 2.4, use version 4.3.0 or earlier
|
41
44
|
* for Ruby 2.3, use version 3.2.0 or earlier
|
42
45
|
* for Ruby versions 2.2, 2.1 and 2.0, use version 2.5.3 or earlier
|
@@ -459,7 +462,7 @@ info.user_id
|
|
459
462
|
|
460
463
|
### File Uploads
|
461
464
|
|
462
|
-
Using the new [Blob Data](
|
465
|
+
Using the new [Blob Data](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm) api feature (500mb limit):
|
463
466
|
|
464
467
|
```ruby
|
465
468
|
client.create('Document', FolderId: '00lE0000000FJ6H',
|
@@ -477,7 +480,7 @@ client.create('Document', FolderId: '00lE0000000FJ6H',
|
|
477
480
|
Body: Base64::encode64(File.read('image.jpg'))
|
478
481
|
```
|
479
482
|
|
480
|
-
_See also: [Inserting or updating blob data](
|
483
|
+
_See also: [Inserting or updating blob data](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_insert_update_blob.htm)_
|
481
484
|
|
482
485
|
* * *
|
483
486
|
|
@@ -572,6 +575,52 @@ end
|
|
572
575
|
Boom, you're now receiving push notifications when Accounts are
|
573
576
|
created/updated.
|
574
577
|
|
578
|
+
#### Composite API
|
579
|
+
|
580
|
+
Restforce supports the [Composite API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_composite.htm).
|
581
|
+
This feature permits the user to send a composite object—that is, a complex
|
582
|
+
object with nested children—in a single API call. Up to 25 requests may be
|
583
|
+
included in a single composite.
|
584
|
+
|
585
|
+
Note that `GET` is not yet implemented for this API.
|
586
|
+
|
587
|
+
```ruby
|
588
|
+
# build up an array of requests:
|
589
|
+
requests << {
|
590
|
+
method: :update,
|
591
|
+
sobject: sobject, # e.g. "Contact"
|
592
|
+
reference_id: reference_id,
|
593
|
+
data: data
|
594
|
+
}
|
595
|
+
|
596
|
+
# send every 25 requests as a subrequest in a single composite call
|
597
|
+
requests.each_slice(25).map do |req_slice|
|
598
|
+
client.composite do |subrequest|
|
599
|
+
req_slice.each do |r|
|
600
|
+
subrequest.send *r.values
|
601
|
+
end
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
# note that we're using `map` to return an array of each responses to each
|
606
|
+
# composite call; 100 requests will produce 4 responses
|
607
|
+
```
|
608
|
+
|
609
|
+
#### Composite Batch API
|
610
|
+
|
611
|
+
Restforce supports the [Composite Batch API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_batch.htm).
|
612
|
+
This feature permits up to 25 subrequests in a single request, though each
|
613
|
+
subrequest counts against the API limit. On the other hand, it has fewer
|
614
|
+
limitations than the Composite API.
|
615
|
+
|
616
|
+
```
|
617
|
+
client.batch do |subrequests|
|
618
|
+
subrequests.create('Object', name: 'test')
|
619
|
+
subrequests.update('Object', id: '123', name: 'test')
|
620
|
+
subrequests.destroy('Object', '123')
|
621
|
+
end
|
622
|
+
```
|
623
|
+
|
575
624
|
#### Replaying Events
|
576
625
|
|
577
626
|
Since API version 37.0, Salesforce stores events for 24 hours and they can be
|
data/lib/restforce/collection.rb
CHANGED
@@ -27,12 +27,26 @@ module Restforce
|
|
27
27
|
@raw_page['records'].size
|
28
28
|
end
|
29
29
|
|
30
|
-
# Return the
|
30
|
+
# Return the number of items in the Collection without making any additional
|
31
|
+
# requests and going through all of the pages of results, one by one. Instead,
|
32
|
+
# we can rely on the total count of results which Salesforce returns.
|
31
33
|
def size
|
32
34
|
@raw_page['totalSize']
|
33
35
|
end
|
34
36
|
alias length size
|
35
37
|
|
38
|
+
def count(*args)
|
39
|
+
# By default, `Enumerable`'s `#count` uses `#each`, which means going through all
|
40
|
+
# of the pages of results, one by one. Instead, we can use `#size` which we have
|
41
|
+
# already overridden to work in a smarter, more efficient way. This only works for
|
42
|
+
# the simple version of `#count` with no arguments. When called with an argument or
|
43
|
+
# a block, you need to know what the items in the collection actually are, so we
|
44
|
+
# call `super` and end up iterating through each item in the collection.
|
45
|
+
return size unless block_given? || !args.empty?
|
46
|
+
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
36
50
|
# Returns true if the size of the Collection is zero.
|
37
51
|
def empty?
|
38
52
|
size.zero?
|
@@ -380,7 +380,7 @@ module Restforce
|
|
380
380
|
end
|
381
381
|
else
|
382
382
|
api_patch "sobjects/#{sobject}/#{field}/" \
|
383
|
-
|
383
|
+
"#{ERB::Util.url_encode(external_id)}", attrs
|
384
384
|
end
|
385
385
|
|
386
386
|
response.body.respond_to?(:fetch) ? response.body.fetch('id', true) : true
|
@@ -61,9 +61,9 @@ module Restforce
|
|
61
61
|
def initialize(opts = {})
|
62
62
|
raise ArgumentError, 'Please specify a hash of options' unless opts.is_a?(Hash)
|
63
63
|
|
64
|
-
@options =
|
64
|
+
@options = Restforce.configuration.options.map do |option|
|
65
65
|
[option, Restforce.configuration.send(option)]
|
66
|
-
end
|
66
|
+
end.to_h
|
67
67
|
|
68
68
|
@options.merge! opts
|
69
69
|
yield builder if block_given?
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'restforce/concerns/verbs'
|
4
|
+
|
5
|
+
module Restforce
|
6
|
+
module Concerns
|
7
|
+
module CompositeAPI
|
8
|
+
extend Restforce::Concerns::Verbs
|
9
|
+
|
10
|
+
define_verbs :post
|
11
|
+
|
12
|
+
def composite(all_or_none: false, collate_subrequests: false)
|
13
|
+
subrequests = Subrequests.new(options)
|
14
|
+
yield(subrequests)
|
15
|
+
|
16
|
+
if subrequests.requests.length > 25
|
17
|
+
raise ArgumentError, 'Cannot have more than 25 subrequests.'
|
18
|
+
end
|
19
|
+
|
20
|
+
properties = {
|
21
|
+
compositeRequest: subrequests.requests,
|
22
|
+
allOrNone: all_or_none,
|
23
|
+
collateSubrequests: collate_subrequests
|
24
|
+
}
|
25
|
+
response = api_post('composite', properties.to_json)
|
26
|
+
|
27
|
+
results = response.body['CompositeResponse']
|
28
|
+
has_errors = results.any? { |result| result['HttpStatusCode'].digits.last == 4 }
|
29
|
+
if all_or_none && has_errors
|
30
|
+
last_error_index = results.rindex { |result| result['HttpStatusCode'] != 412 }
|
31
|
+
last_error = results[last_error_index]
|
32
|
+
raise CompositeAPIError, last_error['Body'][0]['errorCode']
|
33
|
+
end
|
34
|
+
|
35
|
+
results
|
36
|
+
end
|
37
|
+
|
38
|
+
def composite!(collate_subrequests: false, &block)
|
39
|
+
composite(all_or_none: true, collate_subrequests: collate_subrequests, &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
class Subrequests
|
43
|
+
def initialize(options)
|
44
|
+
@options = options
|
45
|
+
@requests = []
|
46
|
+
end
|
47
|
+
attr_reader :options, :requests
|
48
|
+
|
49
|
+
def create(sobject, reference_id, attrs)
|
50
|
+
requests << {
|
51
|
+
method: 'POST',
|
52
|
+
url: composite_api_path(sobject),
|
53
|
+
body: attrs,
|
54
|
+
referenceId: reference_id
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def update(sobject, reference_id, attrs)
|
59
|
+
id = attrs.fetch(attrs.keys.find { |k, _v| k.to_s.casecmp?('id') }, nil)
|
60
|
+
raise ArgumentError, 'Id field missing from attrs.' unless id
|
61
|
+
|
62
|
+
attrs_without_id = attrs.reject { |k, _v| k.to_s.casecmp?('id') }
|
63
|
+
requests << {
|
64
|
+
method: 'PATCH',
|
65
|
+
url: composite_api_path("#{sobject}/#{id}"),
|
66
|
+
body: attrs_without_id,
|
67
|
+
referenceId: reference_id
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
def destroy(sobject, reference_id, id)
|
72
|
+
requests << {
|
73
|
+
method: 'DELETE',
|
74
|
+
url: composite_api_path("#{sobject}/#{id}"),
|
75
|
+
referenceId: reference_id
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def upsert(sobject, reference_id, ext_field, attrs)
|
80
|
+
raise ArgumentError, 'External id field missing.' unless ext_field
|
81
|
+
|
82
|
+
ext_id = attrs.fetch(attrs.keys.find do |k, _v|
|
83
|
+
k.to_s.casecmp?(ext_field.to_s)
|
84
|
+
end, nil)
|
85
|
+
raise ArgumentError, 'External id missing from attrs.' unless ext_id
|
86
|
+
|
87
|
+
attrs_without_ext_id = attrs.reject { |k, _v| k.to_s.casecmp?(ext_field) }
|
88
|
+
requests << {
|
89
|
+
method: 'PATCH',
|
90
|
+
url: composite_api_path("#{sobject}/#{ext_field}/#{ext_id}"),
|
91
|
+
body: attrs_without_ext_id,
|
92
|
+
referenceId: reference_id
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def composite_api_path(path)
|
99
|
+
"/services/data/v#{options[:api_version]}/sobjects/#{path}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -85,7 +85,7 @@ module Restforce
|
|
85
85
|
def valid?(picklist_entry)
|
86
86
|
valid_for = picklist_entry['validFor'].ljust(16, 'A').unpack1('m').
|
87
87
|
unpack('C*')
|
88
|
-
(valid_for[index >> 3] & (0x80 >> index % 8)).positive?
|
88
|
+
(valid_for[index >> 3] & (0x80 >> (index % 8))).positive?
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
data/lib/restforce/error_code.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
module Restforce
|
4
4
|
module ErrorCode
|
5
5
|
GITHUB_ISSUE_URL = "https://github.com/restforce/restforce/issues/new?template=" \
|
6
|
-
|
7
|
-
|
6
|
+
"unhandled-salesforce-error.md&title=Unhandled+Salesforce+error" \
|
7
|
+
"%3A+%3Cinsert+error+code+here%3E"
|
8
8
|
|
9
9
|
# We define all of the known errors returned by Salesforce based on the
|
10
10
|
# documentation at
|
@@ -17,8 +17,12 @@ module Restforce
|
|
17
17
|
|
18
18
|
class AlreadyInProcess < ResponseError; end
|
19
19
|
|
20
|
+
class ApexError < ResponseError; end
|
21
|
+
|
20
22
|
class ApiCurrentlyDisabled < ResponseError; end
|
21
23
|
|
24
|
+
class ApiDisabledForOrg < ResponseError; end
|
25
|
+
|
22
26
|
class AssigneeTypeRequired < ResponseError; end
|
23
27
|
|
24
28
|
class BadCustomEntityParentDomain < ResponseError; end
|
@@ -27,6 +31,8 @@ module Restforce
|
|
27
31
|
|
28
32
|
class BccSelfNotAllowedIfBccComplianceEnabled < ResponseError; end
|
29
33
|
|
34
|
+
class BigObjectUnsupportedOperation < ResponseError; end
|
35
|
+
|
30
36
|
class CannotCascadeProductActive < ResponseError; end
|
31
37
|
|
32
38
|
class CannotChangeFieldTypeOfApexReferencedField < ResponseError; end
|
@@ -233,6 +239,8 @@ module Restforce
|
|
233
239
|
|
234
240
|
class InvalidReadOnlyUserDml < ResponseError; end
|
235
241
|
|
242
|
+
class InvalidReplicationDate < ResponseError; end
|
243
|
+
|
236
244
|
class InvalidSaveAsActivityFlag < ResponseError; end
|
237
245
|
|
238
246
|
class InvalidSessionId < ResponseError; end
|
@@ -303,6 +311,8 @@ module Restforce
|
|
303
311
|
|
304
312
|
class MergeFailed < ResponseError; end
|
305
313
|
|
314
|
+
class MethodNotAllowed < ResponseError; end
|
315
|
+
|
306
316
|
class MissingArgument < ResponseError; end
|
307
317
|
|
308
318
|
class NonuniqueShippingAddress < ResponseError; end
|
@@ -335,6 +345,8 @@ module Restforce
|
|
335
345
|
|
336
346
|
class PrivateContactOnAsset < ResponseError; end
|
337
347
|
|
348
|
+
class QueryTimeout < ResponseError; end
|
349
|
+
|
338
350
|
class RecordInUseByWorkflow < ResponseError; end
|
339
351
|
|
340
352
|
class RequestLimitExceeded < ResponseError; end
|
@@ -396,13 +408,16 @@ module Restforce
|
|
396
408
|
ERROR_EXCEPTION_CLASSES = {
|
397
409
|
"ALL_OR_NONE_OPERATION_ROLLED_BACK" => AllOrNoneOperationRolledBack,
|
398
410
|
"ALREADY_IN_PROCESS" => AlreadyInProcess,
|
411
|
+
"APEX_ERROR" => ApexError,
|
399
412
|
"API_CURRENTLY_DISABLED" => ApiCurrentlyDisabled,
|
413
|
+
"API_DISABLED_FOR_ORG" => ApiDisabledForOrg,
|
400
414
|
"ASSIGNEE_TYPE_REQUIRED" => AssigneeTypeRequired,
|
401
415
|
"BAD_CUSTOM_ENTITY_PARENT_DOMAIN" => BadCustomEntityParentDomain,
|
402
416
|
"BCC_NOT_ALLOWED_IF_BCC_COMPLIANCE_ENABLED" =>
|
403
417
|
BccNotAllowedIfBccComplianceEnabled,
|
404
418
|
"BCC_SELF_NOT_ALLOWED_IF_BCC_COMPLIANCE_ENABLED" =>
|
405
419
|
BccSelfNotAllowedIfBccComplianceEnabled,
|
420
|
+
"BIG_OBJECT_UNSUPPORTED_OPERATION" => BigObjectUnsupportedOperation,
|
406
421
|
"CANNOT_CASCADE_PRODUCT_ACTIVE" => CannotCascadeProductActive,
|
407
422
|
"CANNOT_CHANGE_FIELD_TYPE_OF_APEX_REFERENCED_FIELD" =>
|
408
423
|
CannotChangeFieldTypeOfApexReferencedField,
|
@@ -513,6 +528,7 @@ module Restforce
|
|
513
528
|
"INVALID_PARTNER_NETWORK_STATUS" => InvalidPartnerNetworkStatus,
|
514
529
|
"INVALID_PERSON_ACCOUNT_OPERATION" => InvalidPersonAccountOperation,
|
515
530
|
"INVALID_READ_ONLY_USER_DML" => InvalidReadOnlyUserDml,
|
531
|
+
"INVALID_REPLICATION_DATE" => InvalidReplicationDate,
|
516
532
|
"INVALID_SAVE_AS_ACTIVITY_FLAG" => InvalidSaveAsActivityFlag,
|
517
533
|
"INVALID_SESSION_ID" => InvalidSessionId,
|
518
534
|
"INVALID_STATUS" => InvalidStatus,
|
@@ -548,6 +564,7 @@ module Restforce
|
|
548
564
|
"MAX_TM_RULES_EXCEEDED" => MaxTmRulesExceeded,
|
549
565
|
"MAX_TM_RULE_ITEMS_EXCEEDED" => MaxTmRuleItemsExceeded,
|
550
566
|
"MERGE_FAILED" => MergeFailed,
|
567
|
+
"METHOD_NOT_ALLOWED" => MethodNotAllowed,
|
551
568
|
"MISSING_ARGUMENT" => MissingArgument,
|
552
569
|
"NONUNIQUE_SHIPPING_ADDRESS" => NonuniqueShippingAddress,
|
553
570
|
"NO_APPLICABLE_PROCESS" => NoApplicableProcess,
|
@@ -564,6 +581,7 @@ module Restforce
|
|
564
581
|
"PLATFORM_EVENT_PUBLISH_FAILED" => PlatformEventPublishFailed,
|
565
582
|
"PORTAL_USER_ALREADY_EXISTS_FOR_CONTACT" => PortalUserAlreadyExistsForContact,
|
566
583
|
"PRIVATE_CONTACT_ON_ASSET" => PrivateContactOnAsset,
|
584
|
+
"QUERY_TIMEOUT" => QueryTimeout,
|
567
585
|
"RECORD_IN_USE_BY_WORKFLOW" => RecordInUseByWorkflow,
|
568
586
|
"REQUEST_LIMIT_EXCEEDED" => RequestLimitExceeded,
|
569
587
|
"REQUEST_RUNNING_TOO_LONG" => RequestRunningTooLong,
|
@@ -597,9 +615,9 @@ module Restforce
|
|
597
615
|
def self.get_exception_class(error_code)
|
598
616
|
ERROR_EXCEPTION_CLASSES.fetch(error_code) do |_|
|
599
617
|
warn "[restforce] An unrecognised error code, `#{error_code}` has been " \
|
600
|
-
|
601
|
-
|
602
|
-
|
618
|
+
"received from Salesforce. Instead of raising an error-specific exception" \
|
619
|
+
", we'll raise a generic `ResponseError`. Please report this missing " \
|
620
|
+
"error code on GitHub at <#{GITHUB_ISSUE_URL}>."
|
603
621
|
|
604
622
|
# If we've received an unexpected error where we don't have a specific
|
605
623
|
# class defined, we can return a generic ResponseError instead
|
@@ -609,10 +627,10 @@ module Restforce
|
|
609
627
|
|
610
628
|
def self.const_missing(constant_name)
|
611
629
|
warn "[restforce] You're referring to a Restforce error that isn't defined, " \
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
630
|
+
"`#{name}::#{constant_name}` (for example by trying to `rescue` it). This " \
|
631
|
+
"might be our fault - we've recently made some changes to how errors are " \
|
632
|
+
"defined. If you're sure that this is a valid Salesforce error, then " \
|
633
|
+
"please create an issue on GitHub at <#{GITHUB_ISSUE_URL}>."
|
616
634
|
|
617
635
|
super(constant_name)
|
618
636
|
end
|
@@ -20,9 +20,9 @@ module Restforce
|
|
20
20
|
def call(env)
|
21
21
|
debug('request') do
|
22
22
|
dump url: env[:url].to_s,
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
method: env[:method],
|
24
|
+
headers: env[:request_headers],
|
25
|
+
body: env[:body]
|
26
26
|
end
|
27
27
|
super
|
28
28
|
end
|
@@ -30,8 +30,8 @@ module Restforce
|
|
30
30
|
def on_complete(env)
|
31
31
|
debug('response') do
|
32
32
|
dump status: env[:status].to_s,
|
33
|
-
|
34
|
-
|
33
|
+
headers: env[:response_headers],
|
34
|
+
body: env[:body]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
data/lib/restforce/version.rb
CHANGED
data/lib/restforce.rb
CHANGED
@@ -32,6 +32,7 @@ module Restforce
|
|
32
32
|
autoload :Base, 'restforce/concerns/base'
|
33
33
|
autoload :API, 'restforce/concerns/api'
|
34
34
|
autoload :BatchAPI, 'restforce/concerns/batch_api'
|
35
|
+
autoload :CompositeAPI, 'restforce/concerns/composite_api'
|
35
36
|
end
|
36
37
|
|
37
38
|
module Data
|
@@ -48,6 +49,7 @@ module Restforce
|
|
48
49
|
UnauthorizedError = Class.new(Faraday::ClientError)
|
49
50
|
APIVersionError = Class.new(Error)
|
50
51
|
BatchAPIError = Class.new(Error)
|
52
|
+
CompositeAPIError = Class.new(Error)
|
51
53
|
|
52
54
|
# Inherit from Faraday::ResourceNotFound for backwards-compatibility
|
53
55
|
# Consumers of this library that rescue and handle Faraday::ResourceNotFound
|
data/restforce.gemspec
CHANGED
@@ -22,20 +22,10 @@ Gem::Specification.new do |gem|
|
|
22
22
|
'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md'
|
23
23
|
}
|
24
24
|
|
25
|
-
gem.required_ruby_version = '>= 2.
|
25
|
+
gem.required_ruby_version = '>= 2.6'
|
26
26
|
|
27
27
|
gem.add_dependency 'faraday', '<= 2.0', '>= 0.9.0'
|
28
28
|
gem.add_dependency 'faraday_middleware', ['>= 0.8.8', '<= 2.0']
|
29
|
-
|
30
|
-
gem.add_dependency 'jwt', ['>= 1.5.6']
|
31
|
-
|
32
29
|
gem.add_dependency 'hashie', '>= 1.2.0', '< 5.0'
|
33
|
-
|
34
|
-
gem.add_development_dependency 'faye' unless RUBY_PLATFORM == 'java'
|
35
|
-
gem.add_development_dependency 'rspec', '~> 2.14.0'
|
36
|
-
gem.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1'
|
37
|
-
|
38
|
-
gem.add_development_dependency 'rubocop', '~> 1.9.1'
|
39
|
-
gem.add_development_dependency 'simplecov', '~> 0.21.2'
|
40
|
-
gem.add_development_dependency 'webmock', '~> 3.11.1'
|
30
|
+
gem.add_dependency 'jwt', ['>= 1.5.6']
|
41
31
|
end
|