restforce 4.2.1 → 5.2.4
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 +14 -9
- data/.github/ISSUE_TEMPLATE/unhandled-salesforce-error.md +17 -0
- data/.github/dependabot.yml +19 -0
- data/.rubocop.yml +5 -4
- data/CHANGELOG.md +96 -0
- data/CONTRIBUTING.md +21 -1
- data/Dockerfile +31 -0
- data/Gemfile +10 -7
- data/README.md +94 -21
- data/UPGRADING.md +38 -0
- data/docker-compose.yml +7 -0
- data/lib/restforce/abstract_client.rb +1 -0
- data/lib/restforce/collection.rb +27 -4
- data/lib/restforce/concerns/api.rb +2 -2
- data/lib/restforce/concerns/base.rb +2 -2
- data/lib/restforce/concerns/caching.rb +7 -0
- data/lib/restforce/concerns/composite_api.rb +104 -0
- data/lib/restforce/concerns/picklists.rb +2 -2
- data/lib/restforce/concerns/streaming.rb +1 -3
- data/lib/restforce/config.rb +4 -1
- data/lib/restforce/error_code.rb +647 -0
- data/lib/restforce/file_part.rb +24 -0
- data/lib/restforce/mash.rb +8 -3
- data/lib/restforce/middleware/caching.rb +1 -1
- data/lib/restforce/middleware/logger.rb +8 -7
- data/lib/restforce/middleware/raise_error.rb +3 -4
- data/lib/restforce/middleware.rb +2 -0
- data/lib/restforce/version.rb +1 -1
- data/lib/restforce.rb +6 -7
- data/restforce.gemspec +11 -20
- data/spec/fixtures/sobject/list_view_results_success_response.json +151 -0
- data/spec/integration/abstract_client_spec.rb +41 -32
- data/spec/integration/data/client_spec.rb +6 -2
- data/spec/spec_helper.rb +24 -1
- data/spec/support/client_integration.rb +7 -7
- data/spec/support/concerns.rb +1 -1
- data/spec/support/fixture_helpers.rb +1 -3
- data/spec/support/middleware.rb +1 -2
- data/spec/unit/collection_spec.rb +38 -2
- data/spec/unit/concerns/api_spec.rb +11 -11
- data/spec/unit/concerns/authentication_spec.rb +6 -6
- data/spec/unit/concerns/caching_spec.rb +26 -0
- data/spec/unit/concerns/composite_api_spec.rb +143 -0
- data/spec/unit/concerns/connection_spec.rb +2 -2
- data/spec/unit/concerns/streaming_spec.rb +4 -4
- data/spec/unit/config_spec.rb +1 -1
- data/spec/unit/error_code_spec.rb +61 -0
- data/spec/unit/mash_spec.rb +5 -0
- 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/authentication_spec.rb +11 -5
- data/spec/unit/middleware/gzip_spec.rb +2 -2
- data/spec/unit/middleware/raise_error_spec.rb +29 -10
- data/spec/unit/signed_request_spec.rb +1 -1
- metadata +41 -125
- data/lib/restforce/upload_io.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfdaff5160d8845afd9c6ed3c384c7edf7d9ecb2593d562bae4d9a4812904137
|
4
|
+
data.tar.gz: 8510146b906c8f7f0869a467db96d9bd3416446338a9d237d8c2e633c911cc35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 592471696b0c585cb73bc26cca75267cfc7a2f3543f86449edd4e3ffc5401975cd4ded7cc7a20b63b5854434c06e6e63c48e0f49bf51839b8b8bee15e02113e8
|
7
|
+
data.tar.gz: 71c9272a0799c6e899bbdd56a0380b6ae5b7112d11e56fb3860a10ca0ba0b1dfb9cf58bb25b0bf59ad8f8b38f50360f5f8ccbed4090afa194a67a19a7ae28318
|
data/.circleci/config.yml
CHANGED
@@ -34,23 +34,28 @@ references:
|
|
34
34
|
destination: test-results
|
35
35
|
|
36
36
|
jobs:
|
37
|
-
build-
|
37
|
+
build-ruby31:
|
38
38
|
docker:
|
39
|
-
- image:
|
39
|
+
- image: cimg/ruby:3.1
|
40
40
|
steps: *steps
|
41
|
-
build-
|
41
|
+
build-ruby30:
|
42
42
|
docker:
|
43
|
-
- image:
|
43
|
+
- image: cimg/ruby:3.0
|
44
44
|
steps: *steps
|
45
|
-
build-
|
45
|
+
build-ruby27:
|
46
46
|
docker:
|
47
|
-
- image:
|
47
|
+
- image: cimg/ruby:2.7
|
48
|
+
steps: *steps
|
49
|
+
build-ruby26:
|
50
|
+
docker:
|
51
|
+
- image: cimg/ruby:2.6
|
48
52
|
steps: *steps
|
49
53
|
|
50
54
|
workflows:
|
51
55
|
version: 2
|
52
56
|
tests:
|
53
57
|
jobs:
|
54
|
-
- build-
|
55
|
-
- build-
|
56
|
-
- build-
|
58
|
+
- build-ruby31
|
59
|
+
- build-ruby30
|
60
|
+
- build-ruby27
|
61
|
+
- build-ruby26
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
name: Unhandled Salesforce error
|
3
|
+
about: We've recently changed the way we handle Salesforce errors to define them ahead
|
4
|
+
of time, rather than dynamically. This might mean we're missing some errors. Please
|
5
|
+
use this template to report them.
|
6
|
+
title: 'Unhandled Salesforce error: <insert error code here>'
|
7
|
+
labels: bug
|
8
|
+
assignees: timrogers
|
9
|
+
|
10
|
+
---
|
11
|
+
|
12
|
+
Restforce doesn't have a definition for the error code `INSERT ERROR CODE HERE`.
|
13
|
+
|
14
|
+
I discovered this missing error code because:
|
15
|
+
|
16
|
+
- [ ] I tried to `rescue` it or refer to it in my code
|
17
|
+
- [ ] I got this error back from Salesforce
|
@@ -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
@@ -7,10 +7,11 @@ AllCops:
|
|
7
7
|
Exclude:
|
8
8
|
- .*/**/*
|
9
9
|
- vendor/**/*
|
10
|
-
|
10
|
+
NewCops: enable
|
11
|
+
TargetRubyVersion: 2.6
|
11
12
|
|
12
|
-
# Limit lines to
|
13
|
-
|
13
|
+
# Limit lines to 90 characters.
|
14
|
+
Layout/LineLength:
|
14
15
|
Max: 90
|
15
16
|
|
16
17
|
Metrics/ClassLength:
|
@@ -70,4 +71,4 @@ Naming/FileName:
|
|
70
71
|
- Guardfile
|
71
72
|
|
72
73
|
Lint/UriEscapeUnescape:
|
73
|
-
Enabled: false
|
74
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,99 @@
|
|
1
|
+
# 5.2.4 (Mar 16, 2022)
|
2
|
+
|
3
|
+
* Fix `Restforce::Collection#size` for Salesforce APIs that use the `size` property to return the total number of results, instead of `totalSize` (@kwong-yw)
|
4
|
+
|
5
|
+
# 5.2.3 (Jan 17, 2022)
|
6
|
+
|
7
|
+
* Add official support for Ruby 3.1 (@timrogers)
|
8
|
+
* Fix handling of responses from the Composite API (@robob27)
|
9
|
+
* Fix dependencies to correctly declare that the gem doesn't work with [faraday](https://github.com/lostisland/faraday) `v1.9.0` or later (@timrogers)
|
10
|
+
|
11
|
+
# 5.2.2 (Dec 16, 2021)
|
12
|
+
|
13
|
+
* Handle the `MALFORMED_SEARCH` error returned by Salesforce (@timrogers)
|
14
|
+
|
15
|
+
# 5.2.1 (Dec 8, 2021)
|
16
|
+
|
17
|
+
* Handle the `OPERATION_TOO_LARGE` error returned by Salesforce (@timrogers)
|
18
|
+
* Handle the `INVALID_SIGNUP_COUNTRY` error returned by Salesforce (@timrogers)
|
19
|
+
|
20
|
+
## 5.2.0 (Oct 15, 2021)
|
21
|
+
|
22
|
+
* Add support for Salesforce's Composite API and Composite Batch API (@meenie, @amacdougall)
|
23
|
+
* Improve the performance of counting numbers of query results with `Restforce::Collection#count`, avoiding unnecessary API requests (@jhass)
|
24
|
+
|
25
|
+
## 5.1.1 (Oct 13, 2021)
|
26
|
+
|
27
|
+
* Handle the `INVALID_REPLICATION_DATE` error returned by Salesforce (@michaelwnyc)
|
28
|
+
* Handle the `BIG_OBJECT_UNSUPPORTED_OPERATION` error returned by Salesforce (@remon)
|
29
|
+
|
30
|
+
## 5.1.0 (Aug 26, 2021)
|
31
|
+
|
32
|
+
* Add official support for Ruby 3.0 (@timrogers)
|
33
|
+
* Drop support for Ruby 2.5, which has reached end-of-life (@timrogers)
|
34
|
+
* Handle the `QUERY_TIMEOUT` error returned by Salesforce (@timrogers)
|
35
|
+
* Remove unnecessary development dependencies for the gem, which can just be in the project's `Gemfile` (@timrogers)
|
36
|
+
|
37
|
+
## 5.0.6 (Jun 17, 2021)
|
38
|
+
|
39
|
+
* Handle the `API_DISABLED_FOR_ORG` error returned by Salesforce (@cmac)
|
40
|
+
* Handle the `METHOD_NOT_ALLOWED` error returned by Salesforce (@timrogers)
|
41
|
+
* Handle the `APEX_ERROR` error returned by Salesforce (@timrogers)
|
42
|
+
|
43
|
+
## 5.0.5 (Feb 17, 2021)
|
44
|
+
|
45
|
+
* Handle the `CANNOT_EXECUTE_FLOW_TRIGGER` error returned by Salesforce (@almusavi, @timrogers)
|
46
|
+
|
47
|
+
## 5.0.4 (Jan 18, 2021)
|
48
|
+
|
49
|
+
* Handle the `INVALID_QUERY_LOCATOR` error returned by Salesforce
|
50
|
+
* Handle the `INVALID_OPERATION_WITH_EXPIRED_PASSWORD` error returned by Salesforce
|
51
|
+
* Handle the `FIELD_INTEGRITY_EXCEPTION` error returned by Salesforce
|
52
|
+
* Handle the `FORBIDDEN` error returned by Salesforce
|
53
|
+
* Handle the `ILLEGAL_QUERY_PARAMETER_VALUE` error returned by Salesforce
|
54
|
+
* Handle the `JSON_PARSER_ERROR` error returned by Salesforce
|
55
|
+
|
56
|
+
## 5.0.3 (Sep 8, 2020)
|
57
|
+
|
58
|
+
* Handle the undocumented `EXCEEDED_MAX_SEMIJOIN_SUBSELECTS` error returned by Salesforce (@embertel, @timrogers)
|
59
|
+
|
60
|
+
## 5.0.2 (Sep 6, 2020)
|
61
|
+
|
62
|
+
* Handle the undocumented `REQUEST_LIMIT_EXCEEDED` error returned by Salesforce (@wkirkby, @timrogers)
|
63
|
+
* Handle the undocumented `SERVER_UNAVAILABLE` error returned by Salesforce (@wkirkby, @timrogers)
|
64
|
+
* Refactor the library to be compatible with Rubocop 0.90's cops (this shouldn't introduce any noticeable changes see #569 for detailed changes) (@timrogers)
|
65
|
+
|
66
|
+
## 5.0.1 (Aug 13, 2020)
|
67
|
+
|
68
|
+
* Handle the undocumented `API_CURRENTLY_DISABLED` error returned by Salesforce (@ruipserra, @timrogers)
|
69
|
+
* Handle the undocumented `MALFORMED_QUERY` error returned by Salesforce (@scottserok, @timrogers)
|
70
|
+
* Handle the undocumented `INVALID_QUERY_FILTER_OPERATOR` error returned by Salesforce (@Dantemss, @timrogers)
|
71
|
+
* Add documentation and scripts for running the
|
72
|
+
library's tests using Docker (@ryansch)
|
73
|
+
|
74
|
+
## 5.0.0 (Jul 10, 2020)
|
75
|
+
|
76
|
+
For instructions on upgrading from Restforce 4.x to 5.x, see our ["Upgrading from Restforce 4.x to 5.x"](https://github.com/restforce/restforce/blob/master/UPGRADING.md) guide.
|
77
|
+
|
78
|
+
### Breaking changes
|
79
|
+
|
80
|
+
* __⚠️ Define exception classes for Salesforce errors up-front instead of dynamically at runtime__, *running the risk that we might miss some errors which should be defined*. If any errors are missed, they will be added in patch versions (e.g. `5.0.1`). For more details on this change, see the ["Upgrading from Restforce 4.x to 5.x"](https://github.com/restforce/restforce/blob/master/UPGRADING.md) guide (@presidentbeef, @timrogers).
|
81
|
+
* __⚠️ Deprecate support for Ruby 2.4__, since [Ruby 2.4 reached its end-of-life](https://www.ruby-lang.org/en/news/2020/04/05/support-of-ruby-2-4-has-ended/) in April 2020 (@timrogers)
|
82
|
+
* __⚠️ Change the ancestry of `Restforce::UnauthorizedError` so it inherits from `Faraday::ClientError`, not `Restforce::Error`__. This breaking change was required to expose the response body returned by the API as part of this error - see the non-breaking changes entry below for further details (@michaldbianchi).
|
83
|
+
|
84
|
+
### Non-breaking changes
|
85
|
+
|
86
|
+
* Add support for `lostisland/faraday` v1.x, whilst maintaining support for v0.9.x (@ryansch)
|
87
|
+
* Add `#empty?` method to `Restforce::Collection`, returning whether they are any items in a collection (@bubaflub)
|
88
|
+
* Allow opting-in to caching on a per-call basis with `Restforce::Client#with_caching` (@swaincreates)
|
89
|
+
* Expose the response body from Salesforce on `Restforce::UnauthorizedError` and `Restforce::NotFoundError` (@michaeldbianchi)
|
90
|
+
* Remove the unnecessary depending on the `json` gem, which has been part of the Ruby standard library since v1.9 (@vonTronje)
|
91
|
+
|
92
|
+
|
93
|
+
## 4.2.2 (Jan 23, 2020)
|
94
|
+
|
95
|
+
* Fix `NoMethodError: undefined method '[]' for nil:NilClass` error when generating objects to return (@apurkiss)
|
96
|
+
|
1
97
|
## 4.2.1 (Dec 4, 2019)
|
2
98
|
|
3
99
|
* Handle empty response bodies returned with authentication errors (@sylvandor)
|
data/CONTRIBUTING.md
CHANGED
@@ -34,4 +34,24 @@ Some things that will increase the chance that your pull request is accepted:
|
|
34
34
|
* Write tests.
|
35
35
|
* Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
|
36
36
|
|
37
|
-
*Adapted from [
|
37
|
+
*Adapted from [factory_bot_rails's CONTRIBUTING.md](https://github.com/thoughtbot/factory_bot_rails/blob/master/CONTRIBUTING.md).*
|
38
|
+
|
39
|
+
## Docker
|
40
|
+
|
41
|
+
If you'd rather use a docker container to run the tests, you can use the following instructions.
|
42
|
+
|
43
|
+
To set up the container image:
|
44
|
+
|
45
|
+
`docker-compose build --pull`
|
46
|
+
|
47
|
+
To run specs:
|
48
|
+
|
49
|
+
`docker-compose run --rm restforce rspec`
|
50
|
+
|
51
|
+
To run rubocop:
|
52
|
+
|
53
|
+
`docker-compose run --rm restforce rubocop`
|
54
|
+
|
55
|
+
To reset the bundler cache:
|
56
|
+
|
57
|
+
`docker-compose down -v`
|
data/Dockerfile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
FROM ruby:2.6.5-alpine
|
2
|
+
|
3
|
+
RUN apk add --no-cache \
|
4
|
+
ca-certificates \
|
5
|
+
wget \
|
6
|
+
openssl \
|
7
|
+
bash \
|
8
|
+
build-base \
|
9
|
+
git \
|
10
|
+
sqlite-dev \
|
11
|
+
tzdata \
|
12
|
+
tini
|
13
|
+
|
14
|
+
ENV LANG en_US.UTF-8
|
15
|
+
ENV LANGUAGE en_US:en
|
16
|
+
ENV LC_ALL en_US.UTF-8
|
17
|
+
|
18
|
+
ENV BUNDLER_VERSION 2.1.4
|
19
|
+
RUN gem install bundler -v ${BUNDLER_VERSION} -i /usr/local/lib/ruby/gems/$(ls /usr/local/lib/ruby/gems) --force
|
20
|
+
|
21
|
+
WORKDIR /srv
|
22
|
+
|
23
|
+
COPY Gemfile restforce.gemspec /srv/
|
24
|
+
COPY lib/restforce/version.rb /srv/lib/restforce/version.rb
|
25
|
+
|
26
|
+
RUN bundle install
|
27
|
+
|
28
|
+
COPY . /srv/
|
29
|
+
|
30
|
+
ENTRYPOINT ["/sbin/tini", "-g", "--", "bundle", "exec"]
|
31
|
+
CMD ["rspec"]
|
data/Gemfile
CHANGED
@@ -3,12 +3,15 @@
|
|
3
3
|
source 'https://rubygems.org'
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
gem '
|
6
|
+
gem 'faye' unless RUBY_PLATFORM == 'java'
|
7
|
+
gem 'guard-rspec'
|
8
|
+
gem 'guard-rubocop'
|
7
9
|
gem 'jruby-openssl', platforms: :jruby
|
8
|
-
gem 'jwt'
|
9
10
|
gem 'rake'
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
gem 'rspec', '~> 3.11.0'
|
12
|
+
gem 'rspec-collection_matchers', '~> 1.2.0'
|
13
|
+
gem 'rspec-its', '~> 1.3.0'
|
14
|
+
gem 'rspec_junit_formatter', '~> 0.5.1'
|
15
|
+
gem 'rubocop', '~> 1.26.0'
|
16
|
+
gem 'simplecov', '~> 0.21.2'
|
17
|
+
gem 'webmock', '~> 3.14.0'
|
data/README.md
CHANGED
@@ -8,10 +8,12 @@ Restforce is a ruby gem for the [Salesforce REST api](http://www.salesforce.com/
|
|
8
8
|
Features include:
|
9
9
|
|
10
10
|
* A clean and modular architecture using [Faraday middleware](https://github.com/technoweenie/faraday) and [Hashie::Mash](https://github.com/intridea/hashie/tree/v1.2.0)'d responses.
|
11
|
-
* Support for interacting with multiple users from different
|
11
|
+
* Support for interacting with multiple users from different organizations.
|
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.
|
@@ -19,13 +21,13 @@ Features include:
|
|
19
21
|
* Support for dependent picklists.
|
20
22
|
* Support for decoding [Force.com Canvas](http://www.salesforce.com/us/developer/docs/platform_connectpre/canvas_framework.pdf) signed requests. (NEW!)
|
21
23
|
|
22
|
-
[Official Website](
|
24
|
+
[Official Website](https://restforce.github.io/) | [Documentation](http://rubydoc.info/gems/restforce/frames) | [Changelog](https://github.com/restforce/restforce/tree/master/CHANGELOG.md)
|
23
25
|
|
24
26
|
## Installation
|
25
27
|
|
26
28
|
Add this line to your application's Gemfile:
|
27
29
|
|
28
|
-
gem 'restforce', '~>
|
30
|
+
gem 'restforce', '~> 5.2.4'
|
29
31
|
|
30
32
|
And then execute:
|
31
33
|
|
@@ -35,7 +37,13 @@ Or install it yourself as:
|
|
35
37
|
|
36
38
|
$ gem install restforce
|
37
39
|
|
38
|
-
__As of
|
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:
|
41
|
+
|
42
|
+
* for Ruby 2.5, use version 5.0.6 or earlier
|
43
|
+
* for Ruby 2.4, use version 4.3.0 or earlier
|
44
|
+
* for Ruby 2.3, use version 3.2.0 or earlier
|
45
|
+
* for Ruby versions 2.2, 2.1 and 2.0, use version 2.5.3 or earlier
|
46
|
+
* for Ruby 1.9.3, use version 2.4.2
|
39
47
|
|
40
48
|
This gem is versioned using [Semantic Versioning](http://semver.org/), so you can be confident when updating that there will not be breaking changes outside of a major version (following format MAJOR.MINOR.PATCH, so for instance moving from 3.1.0 to 4.0.0 would be allowed to include incompatible API changes). See the [changelog](https://github.com/restforce/restforce/tree/master/CHANGELOG.md) for details on what has changed in each version.
|
41
49
|
|
@@ -48,7 +56,7 @@ so you can do things like `client.query('select Id, (select Name from Children__
|
|
48
56
|
### Initialization
|
49
57
|
|
50
58
|
Which authentication method you use really depends on your use case. If you're
|
51
|
-
building an application where many users from different
|
59
|
+
building an application where many users from different organizations are authenticated
|
52
60
|
through oauth and you need to interact with data in their org on their behalf,
|
53
61
|
you should use the OAuth token authentication method.
|
54
62
|
|
@@ -78,7 +86,7 @@ client = Restforce.new(oauth_token: 'access_token',
|
|
78
86
|
api_version: '41.0')
|
79
87
|
```
|
80
88
|
|
81
|
-
The middleware will use the `refresh_token` automatically to acquire a new `access_token` if the existing `access_token` is invalid.
|
89
|
+
The middleware will use the `refresh_token` automatically to acquire a new `access_token` if the existing `access_token` is invalid. The refresh process uses the `host` option so make sure that is set correctly for sandbox organizations.
|
82
90
|
|
83
91
|
`authentication_callback` is a proc that handles the response from Salesforce when the `refresh_token` is used to obtain a new `access_token`. This allows the `access_token` to be saved for re-use later - otherwise subsequent API calls will continue the cycle of "auth failure/issue new access_token/auth success".
|
84
92
|
|
@@ -142,7 +150,17 @@ export SALESFORCE_API_VERSION="41.0"
|
|
142
150
|
client = Restforce.new
|
143
151
|
```
|
144
152
|
|
145
|
-
|
153
|
+
#### Sandbox Organizations
|
154
|
+
|
155
|
+
You can connect to sandbox organizations by specifying a host. The default host is
|
156
|
+
'login.salesforce.com':
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
client = Restforce.new(host: 'test.salesforce.com')
|
160
|
+
```
|
161
|
+
The host can also be set with the environment variable `SALESFORCE_HOST`.
|
162
|
+
|
163
|
+
#### Proxy Support
|
146
164
|
|
147
165
|
You can specify a HTTP proxy using the `proxy_uri` option, as follows, or by setting the `SALESFORCE_PROXY_URI` environment variable:
|
148
166
|
|
@@ -158,16 +176,6 @@ client = Restforce.new(username: 'foo',
|
|
158
176
|
|
159
177
|
You may specify a username and password for the proxy with a URL along the lines of 'http://user:password@proxy.example.com:123'.
|
160
178
|
|
161
|
-
#### Sandbox Orgs
|
162
|
-
|
163
|
-
You can connect to sandbox orgs by specifying a host. The default host is
|
164
|
-
'login.salesforce.com':
|
165
|
-
|
166
|
-
```ruby
|
167
|
-
client = Restforce.new(host: 'test.salesforce.com')
|
168
|
-
```
|
169
|
-
The host can also be set with the environment variable `SALESFORCE_HOST`.
|
170
|
-
|
171
179
|
#### Global configuration
|
172
180
|
|
173
181
|
You can set any of the options passed into `Restforce.new` globally:
|
@@ -328,8 +336,11 @@ client.update('Account', Id: '0016000000MRatd', Name: 'Whizbang Corp')
|
|
328
336
|
```ruby
|
329
337
|
# Update the record with external `External__c` external ID set to '12'
|
330
338
|
client.upsert('Account', 'External__c', External__c: 12, Name: 'Foobar')
|
339
|
+
# => true or "RecordId"
|
331
340
|
```
|
332
341
|
|
342
|
+
The upsert method will return the record Id if included in the response body from the Salesforce API; otherwise, it returns true. Currently the Salesforce API only returns the Id for newly created records.
|
343
|
+
|
333
344
|
### destroy
|
334
345
|
|
335
346
|
```ruby
|
@@ -451,13 +462,13 @@ info.user_id
|
|
451
462
|
|
452
463
|
### File Uploads
|
453
464
|
|
454
|
-
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):
|
455
466
|
|
456
467
|
```ruby
|
457
468
|
client.create('Document', FolderId: '00lE0000000FJ6H',
|
458
469
|
Description: 'Document test',
|
459
470
|
Name: 'My image',
|
460
|
-
Body: Restforce::
|
471
|
+
Body: Restforce::FilePart.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg')
|
461
472
|
```
|
462
473
|
|
463
474
|
Using base64 encoded data (37.5mb limit):
|
@@ -469,7 +480,7 @@ client.create('Document', FolderId: '00lE0000000FJ6H',
|
|
469
480
|
Body: Base64::encode64(File.read('image.jpg'))
|
470
481
|
```
|
471
482
|
|
472
|
-
_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)_
|
473
484
|
|
474
485
|
* * *
|
475
486
|
|
@@ -564,6 +575,52 @@ end
|
|
564
575
|
Boom, you're now receiving push notifications when Accounts are
|
565
576
|
created/updated.
|
566
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
|
+
|
567
624
|
#### Replaying Events
|
568
625
|
|
569
626
|
Since API version 37.0, Salesforce stores events for 24 hours and they can be
|
@@ -688,7 +745,23 @@ client.without_caching do
|
|
688
745
|
end
|
689
746
|
```
|
690
747
|
|
691
|
-
|
748
|
+
If you prefer to opt in to caching on a per-request, you can do so by using .with_caching and
|
749
|
+
setting the `use_cache` config option to false:
|
750
|
+
|
751
|
+
```ruby
|
752
|
+
Restforce.configure do |config|
|
753
|
+
config.cache = Rails.cache
|
754
|
+
config.use_cache = false
|
755
|
+
end
|
756
|
+
```
|
757
|
+
|
758
|
+
```ruby
|
759
|
+
client.with_caching do
|
760
|
+
client.query('select Id from Account')
|
761
|
+
end
|
762
|
+
```
|
763
|
+
|
764
|
+
Caching is done based on your authentication credentials, so cached responses will not be shared between different Salesforce logins.
|
692
765
|
|
693
766
|
* * *
|
694
767
|
|
data/UPGRADING.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Upgrading from Restforce 4.x to 5.x
|
2
|
+
|
3
|
+
__There are three breaking changes introduced in Restforce 5.x__. In this guide, you'll learn about these changes and what you should check in your code to make sure that it will work with the latest version of the library.
|
4
|
+
|
5
|
+
## Error classes are now defined up-front, rather than dynamically at runtime
|
6
|
+
|
7
|
+
__Likelyhood of impact__: Moderate
|
8
|
+
|
9
|
+
The Salesforce REST API can return a range of `errorCode`s representing different kinds of errors. To make these easy to
|
10
|
+
handle in your code, we want to turn these into individual, specific exception classes in the `Restforce::ErrorCode` namespace that inherit from `Restforce:: ResponseError`.
|
11
|
+
|
12
|
+
Up until now, these exception classes have been defined dynamically at runtime which has some disadvantages - see the [pull request](https://github.com/restforce/restforce/pull/551) for more details.
|
13
|
+
|
14
|
+
In this version, we switch to defining them up-front in the code based on a list in the Salesforce documentation. There is a risk that we might have missed some errors which should be defined. If any errors are missed, they will be added in patch versions (e.g. `5.0.1`).
|
15
|
+
|
16
|
+
If your application won't run because you are referring to an exception class that no longer exists, or you see warnings logged anywhere, please [create an issue](https://github.com/restforce/restforce/issues/new?template=unhandled-salesforce-error.md&title=Unhandled+Salesforce+error%3A+%3Cinsert+error+code+here%3E).
|
17
|
+
|
18
|
+
## Ruby 2.4 is no longer supported
|
19
|
+
|
20
|
+
__Likelyhood of impact__: Moderate
|
21
|
+
|
22
|
+
As of [5th April 2020](https://www.ruby-lang.org/en/news/2020/04/05/support-of-ruby-2-4-has-ended/), Ruby 2.4 is no longer officially supported as an active version of the Ruby language. That means that it will not receive patches and security fixes.
|
23
|
+
|
24
|
+
Accordingly, we've dropped support for Ruby 2.4 and earlier in the Restforce library. It *may* be compatible, bu we don't guarantee this or enforce it with automated tests.
|
25
|
+
|
26
|
+
Before you update to Restforce 5.x, you'll need to switch to Ruby 2.5 or later. The current version of Ruby at the time of wriing is 2.7.
|
27
|
+
|
28
|
+
## `Restforce::UnauthorizedError` no longer inherits from `Restforce::Error`
|
29
|
+
|
30
|
+
__Likelyhood of impact__: Low
|
31
|
+
|
32
|
+
Previously, the `Restforce::UnauthorizedError` returned when the library couldn't authenticate with the Salesforce API inherits from `Restforce::Error`. So, if you used `rescue Restforce::Error` in your code, you'd catch these exceptions.
|
33
|
+
|
34
|
+
We've now changed this exception class to inherit from `Faraday::ClientError` which allows the response body returned from the Salesforce API to be attached to the error.
|
35
|
+
|
36
|
+
If you refer to `Restforce::Error` anywhere in your code, you should check whether you also need to take into account `Restforce::UnauthorizedError`.
|
37
|
+
|
38
|
+
If you refer to `Faraday::ClientError` anywhere in your code, you should check that you want the case where Restforce can't authenticate to be included.
|
data/docker-compose.yml
ADDED
data/lib/restforce/collection.rb
CHANGED
@@ -12,12 +12,12 @@ module Restforce
|
|
12
12
|
end
|
13
13
|
|
14
14
|
# Yield each value on each page.
|
15
|
-
def each
|
15
|
+
def each(&block)
|
16
16
|
@raw_page['records'].each { |record| yield Restforce::Mash.build(record, @client) }
|
17
17
|
|
18
18
|
np = next_page
|
19
19
|
while np
|
20
|
-
np.current_page.each
|
20
|
+
np.current_page.each(&block)
|
21
21
|
np = np.next_page
|
22
22
|
end
|
23
23
|
end
|
@@ -27,12 +27,35 @@ 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.
|
33
|
+
#
|
34
|
+
# Most of the Salesforce API returns this in the `totalSize` attribute. For
|
35
|
+
# some reason, the [List View Results](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_listviewresults.htm)
|
36
|
+
# endpoint (and maybe others?!) uses the `size` attribute.
|
31
37
|
def size
|
32
|
-
@raw_page['totalSize']
|
38
|
+
@raw_page['totalSize'] || @raw_page['size']
|
33
39
|
end
|
34
40
|
alias length size
|
35
41
|
|
42
|
+
def count(*args)
|
43
|
+
# By default, `Enumerable`'s `#count` uses `#each`, which means going through all
|
44
|
+
# of the pages of results, one by one. Instead, we can use `#size` which we have
|
45
|
+
# already overridden to work in a smarter, more efficient way. This only works for
|
46
|
+
# the simple version of `#count` with no arguments. When called with an argument or
|
47
|
+
# a block, you need to know what the items in the collection actually are, so we
|
48
|
+
# call `super` and end up iterating through each item in the collection.
|
49
|
+
return size unless block_given? || !args.empty?
|
50
|
+
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns true if the size of the Collection is zero.
|
55
|
+
def empty?
|
56
|
+
size.zero?
|
57
|
+
end
|
58
|
+
|
36
59
|
# Return array of the elements on the current page
|
37
60
|
def current_page
|
38
61
|
first(@raw_page['records'].size)
|
@@ -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
|
@@ -510,7 +510,7 @@ module Restforce
|
|
510
510
|
|
511
511
|
# Internal: Errors that should be rescued from in non-bang methods
|
512
512
|
def exceptions
|
513
|
-
[Faraday::
|
513
|
+
[Faraday::Error]
|
514
514
|
end
|
515
515
|
end
|
516
516
|
end
|
@@ -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.to_h do |option|
|
65
65
|
[option, Restforce.configuration.send(option)]
|
66
|
-
end
|
66
|
+
end
|
67
67
|
|
68
68
|
@options.merge! opts
|
69
69
|
yield builder if block_given?
|