restforce 4.2.1 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/unhandled-salesforce-error.md +17 -0
  3. data/.github/dependabot.yml +10 -0
  4. data/.github/funding.yml +1 -0
  5. data/.github/workflows/build.yml +23 -0
  6. data/.github/workflows/faraday.yml +27 -0
  7. data/.rubocop.yml +5 -4
  8. data/CHANGELOG.md +115 -0
  9. data/CONTRIBUTING.md +21 -1
  10. data/Dockerfile +31 -0
  11. data/Gemfile +15 -7
  12. data/README.md +102 -24
  13. data/UPGRADING.md +67 -0
  14. data/docker-compose.yml +7 -0
  15. data/lib/restforce/abstract_client.rb +1 -0
  16. data/lib/restforce/collection.rb +27 -4
  17. data/lib/restforce/concerns/api.rb +3 -2
  18. data/lib/restforce/concerns/base.rb +2 -2
  19. data/lib/restforce/concerns/caching.rb +7 -0
  20. data/lib/restforce/concerns/composite_api.rb +104 -0
  21. data/lib/restforce/concerns/connection.rb +1 -1
  22. data/lib/restforce/concerns/picklists.rb +2 -2
  23. data/lib/restforce/concerns/streaming.rb +1 -3
  24. data/lib/restforce/config.rb +14 -9
  25. data/lib/restforce/error_code.rb +650 -0
  26. data/lib/restforce/file_part.rb +32 -0
  27. data/lib/restforce/mash.rb +8 -3
  28. data/lib/restforce/middleware/authentication.rb +1 -0
  29. data/lib/restforce/middleware/caching.rb +140 -15
  30. data/lib/restforce/middleware/json_request.rb +90 -0
  31. data/lib/restforce/middleware/json_response.rb +85 -0
  32. data/lib/restforce/middleware/logger.rb +14 -9
  33. data/lib/restforce/middleware/raise_error.rb +13 -5
  34. data/lib/restforce/middleware.rb +2 -0
  35. data/lib/restforce/version.rb +1 -1
  36. data/lib/restforce.rb +15 -14
  37. data/restforce.gemspec +13 -21
  38. data/spec/fixtures/sobject/list_view_results_success_response.json +151 -0
  39. data/spec/integration/abstract_client_spec.rb +56 -35
  40. data/spec/integration/data/client_spec.rb +6 -2
  41. data/spec/spec_helper.rb +24 -1
  42. data/spec/support/client_integration.rb +7 -7
  43. data/spec/support/concerns.rb +1 -1
  44. data/spec/support/fixture_helpers.rb +1 -3
  45. data/spec/support/middleware.rb +1 -2
  46. data/spec/unit/collection_spec.rb +38 -2
  47. data/spec/unit/concerns/api_spec.rb +22 -15
  48. data/spec/unit/concerns/authentication_spec.rb +6 -6
  49. data/spec/unit/concerns/caching_spec.rb +26 -0
  50. data/spec/unit/concerns/composite_api_spec.rb +143 -0
  51. data/spec/unit/concerns/connection_spec.rb +2 -2
  52. data/spec/unit/concerns/streaming_spec.rb +4 -4
  53. data/spec/unit/config_spec.rb +2 -2
  54. data/spec/unit/error_code_spec.rb +61 -0
  55. data/spec/unit/mash_spec.rb +5 -0
  56. data/spec/unit/middleware/authentication/jwt_bearer_spec.rb +24 -8
  57. data/spec/unit/middleware/authentication/password_spec.rb +12 -4
  58. data/spec/unit/middleware/authentication/token_spec.rb +12 -4
  59. data/spec/unit/middleware/authentication_spec.rb +14 -8
  60. data/spec/unit/middleware/gzip_spec.rb +2 -2
  61. data/spec/unit/middleware/raise_error_spec.rb +29 -10
  62. data/spec/unit/signed_request_spec.rb +1 -1
  63. metadata +64 -187
  64. data/.circleci/config.yml +0 -56
  65. data/lib/restforce/upload_io.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c4f7647ad705f0f4eac359a3b1e792ab4603e9ae4d177570e9369734f7ff3356
4
- data.tar.gz: 7fc076cb9239ebd513926e068d5d1e4ebec01cbb5245e919fd165ea5bf7b841c
3
+ metadata.gz: 9aade8a096cdf3f75ed27ec3d2f8393b6c2798875a3eb25fa5d7c3506532f104
4
+ data.tar.gz: b7d98630ac5c44018f4a30bcd17c14bc6d89c3d50fb27331270e7e94cb64e1a8
5
5
  SHA512:
6
- metadata.gz: ad1cfc119e9d3a64d5491c667254647a1e79298bebb7c036dee95f87b2a6823f0ed5fbb862dc29c6d25166399042767ecae5520498726fa4025b99b439bcd9f1
7
- data.tar.gz: f8e0ab3e2cc1e74e4a1d8d50da2ca8b5bcb13436765993c8737582703248c1c47ca2c6ff02430f19390c02f1b5d95960e6d40e5510ef53e5b25d4e61add35ecc
6
+ metadata.gz: 4d8e4d1d84a12806a0e913a0ca0e64d481584fc774abeb2f968c95cff2d9e92699a872c8f06fe0f03eca6a838345d1b7dfebed6decacfb6f28f72f26e2cae033
7
+ data.tar.gz: 04a9c55df3fd6e49491b0a87a5da2b5f1bdd816c5f1256810770c790ec27d8aa264e537fda96b029d8ba11ce1f1872510507004e9d692cf34360da42a7252844
@@ -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,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ - package-ecosystem: 'github-actions'
8
+ directory: '/'
9
+ schedule:
10
+ interval: 'daily'
@@ -0,0 +1 @@
1
+ github: [restforce]
@@ -0,0 +1,23 @@
1
+ name: 'Build'
2
+ on: push
3
+ jobs:
4
+ lint-and-test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ fail-fast: false
8
+ matrix:
9
+ ruby_version: ['2.7', '3.0', '3.1', '3.2.0-preview1']
10
+ steps:
11
+ - name: Checkout code
12
+ uses: actions/checkout@v3
13
+ - name: Setup Ruby ${{ matrix.ruby_version }}
14
+ uses: ruby/setup-ruby@v1
15
+ with:
16
+ bundler-cache: true
17
+ ruby-version: ${{ matrix.ruby_version }}
18
+ - name: Install dependencies
19
+ run: bundle install
20
+ - name: Lint Ruby files
21
+ run: bundle exec rubocop
22
+ - name: Run RSpec tests
23
+ run: bundle exec rspec
@@ -0,0 +1,27 @@
1
+ name: 'Test against supported Faraday minor versions'
2
+ on: push
3
+ jobs:
4
+ lint-and-test:
5
+ runs-on: ubuntu-latest
6
+ strategy:
7
+ fail-fast: false
8
+ matrix:
9
+ # Normally, we only test the most recent patch version for any given minor version.
10
+ # For v2.0.x, we test v2.0.0 and v2.0.1 because v2.0.0 has a special behaviour where
11
+ # the Net::HTTP adapter is not included. See
12
+ # https://github.com/lostisland/faraday/blob/main/UPGRADING.md#faraday-20.
13
+ faraday_version: ['1.1.0', '1.2.0', '1.3.1', '1.4.1', '1.5.1', '1.6.0', '1.7.2', '1.8.0', '1.9.3', '1.10.0', '2.0.0', '2.0.1', '2.1.0', '2.2.0', '2.3.0', '2.4.0']
14
+ env:
15
+ FARADAY_VERSION: ~> ${{ matrix.faraday_version }}
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v3
19
+ - name: Setup Ruby ${{ matrix.ruby_version }}
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ bundler-cache: true
23
+ ruby-version: 3.1
24
+ - name: Install dependencies
25
+ run: bundle install
26
+ - name: Run RSpec tests
27
+ run: bundle exec rspec
data/.rubocop.yml CHANGED
@@ -7,10 +7,11 @@ AllCops:
7
7
  Exclude:
8
8
  - .*/**/*
9
9
  - vendor/**/*
10
- TargetRubyVersion: 2.4
10
+ NewCops: enable
11
+ TargetRubyVersion: 2.7
11
12
 
12
- # Limit lines to 80 characters.
13
- Metrics/LineLength:
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,118 @@
1
+ # 6.0.0 (Sep 9 2022)
2
+
3
+ __This version contains breaking changes. For help with upgrading, see [`UPGRADING.md`](https://github.com/restforce/restforce/blob/main/UPGRADING.md).__
4
+
5
+ * __⚠️ Drop support for Ruby 2.6__, since [Ruby 2.6 has reached its end-of-life](https://www.ruby-lang.org/en/downloads/) (@timrogers)
6
+ * __⚠️ Drop compatability with `faraday` versions before `v1.1.0`__ (@timrogers)
7
+ * Add support for `faraday` versions `v2.0.0` onwards (@timrogers)
8
+
9
+ *This version was also released as [`v6.0.0.rc.1`](https://github.com/restforce/restforce/releases/tag/v6.0.0.rc.1) on Aug 4 2022.*
10
+
11
+ # 5.3.1 (Jul 19 2022)
12
+
13
+ * Handle the `EXCEEDED_ID_LIMIT` error returned by the Salesforce API (@timrogers, @yashshah1)
14
+
15
+ # 5.3.0 (May 30, 2022)
16
+
17
+ * Add support for Faraday v1.9.x and v1.10.0 (@magni-, @timrogers)
18
+ * Follow redirects during authentication to support Lightning URLs (e.g. `*.lightning.force.com` instead of `*.my.salesforce.com`) (@nhocki)
19
+
20
+ # 5.2.4 (Mar 16, 2022)
21
+
22
+ * Fix `Restforce::Collection#size` for Salesforce APIs that use the `size` property to return the total number of results, instead of `totalSize` (@kwong-yw)
23
+
24
+ # 5.2.3 (Jan 17, 2022)
25
+
26
+ * Add official support for Ruby 3.1 (@timrogers)
27
+ * Fix handling of responses from the Composite API (@robob27)
28
+ * Fix dependencies to correctly declare that the gem doesn't work with [faraday](https://github.com/lostisland/faraday) `v1.9.0` or later (@timrogers)
29
+
30
+ # 5.2.2 (Dec 16, 2021)
31
+
32
+ * Handle the `MALFORMED_SEARCH` error returned by Salesforce (@timrogers)
33
+
34
+ # 5.2.1 (Dec 8, 2021)
35
+
36
+ * Handle the `OPERATION_TOO_LARGE` error returned by Salesforce (@timrogers)
37
+ * Handle the `INVALID_SIGNUP_COUNTRY` error returned by Salesforce (@timrogers)
38
+
39
+ ## 5.2.0 (Oct 15, 2021)
40
+
41
+ * Add support for Salesforce's Composite API and Composite Batch API (@meenie, @amacdougall)
42
+ * Improve the performance of counting numbers of query results with `Restforce::Collection#count`, avoiding unnecessary API requests (@jhass)
43
+
44
+ ## 5.1.1 (Oct 13, 2021)
45
+
46
+ * Handle the `INVALID_REPLICATION_DATE` error returned by Salesforce (@michaelwnyc)
47
+ * Handle the `BIG_OBJECT_UNSUPPORTED_OPERATION` error returned by Salesforce (@remon)
48
+
49
+ ## 5.1.0 (Aug 26, 2021)
50
+
51
+ * Add official support for Ruby 3.0 (@timrogers)
52
+ * Drop support for Ruby 2.5, which has reached end-of-life (@timrogers)
53
+ * Handle the `QUERY_TIMEOUT` error returned by Salesforce (@timrogers)
54
+ * Remove unnecessary development dependencies for the gem, which can just be in the project's `Gemfile` (@timrogers)
55
+
56
+ ## 5.0.6 (Jun 17, 2021)
57
+
58
+ * Handle the `API_DISABLED_FOR_ORG` error returned by Salesforce (@cmac)
59
+ * Handle the `METHOD_NOT_ALLOWED` error returned by Salesforce (@timrogers)
60
+ * Handle the `APEX_ERROR` error returned by Salesforce (@timrogers)
61
+
62
+ ## 5.0.5 (Feb 17, 2021)
63
+
64
+ * Handle the `CANNOT_EXECUTE_FLOW_TRIGGER` error returned by Salesforce (@almusavi, @timrogers)
65
+
66
+ ## 5.0.4 (Jan 18, 2021)
67
+
68
+ * Handle the `INVALID_QUERY_LOCATOR` error returned by Salesforce
69
+ * Handle the `INVALID_OPERATION_WITH_EXPIRED_PASSWORD` error returned by Salesforce
70
+ * Handle the `FIELD_INTEGRITY_EXCEPTION` error returned by Salesforce
71
+ * Handle the `FORBIDDEN` error returned by Salesforce
72
+ * Handle the `ILLEGAL_QUERY_PARAMETER_VALUE` error returned by Salesforce
73
+ * Handle the `JSON_PARSER_ERROR` error returned by Salesforce
74
+
75
+ ## 5.0.3 (Sep 8, 2020)
76
+
77
+ * Handle the undocumented `EXCEEDED_MAX_SEMIJOIN_SUBSELECTS` error returned by Salesforce (@embertel, @timrogers)
78
+
79
+ ## 5.0.2 (Sep 6, 2020)
80
+
81
+ * Handle the undocumented `REQUEST_LIMIT_EXCEEDED` error returned by Salesforce (@wkirkby, @timrogers)
82
+ * Handle the undocumented `SERVER_UNAVAILABLE` error returned by Salesforce (@wkirkby, @timrogers)
83
+ * 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)
84
+
85
+ ## 5.0.1 (Aug 13, 2020)
86
+
87
+ * Handle the undocumented `API_CURRENTLY_DISABLED` error returned by Salesforce (@ruipserra, @timrogers)
88
+ * Handle the undocumented `MALFORMED_QUERY` error returned by Salesforce (@scottserok, @timrogers)
89
+ * Handle the undocumented `INVALID_QUERY_FILTER_OPERATOR` error returned by Salesforce (@Dantemss, @timrogers)
90
+ * Add documentation and scripts for running the
91
+ library's tests using Docker (@ryansch)
92
+
93
+ ## 5.0.0 (Jul 10, 2020)
94
+
95
+ 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.
96
+
97
+ ### Breaking changes
98
+
99
+ * __⚠️ 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).
100
+ * __⚠️ 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)
101
+ * __⚠️ 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).
102
+
103
+ ### Non-breaking changes
104
+
105
+ * Add support for `lostisland/faraday` v1.x, whilst maintaining support for v0.9.x (@ryansch)
106
+ * Add `#empty?` method to `Restforce::Collection`, returning whether they are any items in a collection (@bubaflub)
107
+ * Allow opting-in to caching on a per-call basis with `Restforce::Client#with_caching` (@swaincreates)
108
+ * Expose the response body from Salesforce on `Restforce::UnauthorizedError` and `Restforce::NotFoundError` (@michaeldbianchi)
109
+ * Remove the unnecessary depending on the `json` gem, which has been part of the Ruby standard library since v1.9 (@vonTronje)
110
+
111
+
112
+ ## 4.2.2 (Jan 23, 2020)
113
+
114
+ * Fix `NoMethodError: undefined method '[]' for nil:NilClass` error when generating objects to return (@apurkiss)
115
+
1
116
  ## 4.2.1 (Dec 4, 2019)
2
117
 
3
118
  * 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 [factory_girl_rails's CONTRIBUTING.md](https://github.com/thoughtbot/factory_girl_rails/blob/master/CONTRIBUTING.md).*
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,20 @@
3
3
  source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
- gem 'faraday', '~> 0.17.0'
6
+ faraday_version = ENV.fetch('FARADAY_VERSION', '~> 1.8.0')
7
+
8
+ # Enable us to explicitly pick a Faraday version when running tests
9
+ gem 'faraday', faraday_version
10
+ gem 'faraday-typhoeus', '~> 0.2.1' unless faraday_version.start_with?("~> 1")
11
+ gem 'faye' unless RUBY_PLATFORM == 'java'
12
+ gem 'guard-rspec'
13
+ gem 'guard-rubocop'
7
14
  gem 'jruby-openssl', platforms: :jruby
8
- gem 'jwt'
9
15
  gem 'rake'
10
-
11
- group :development do
12
- gem 'guard-rspec'
13
- gem 'guard-rubocop'
14
- end
16
+ gem 'rspec', '~> 3.11.0'
17
+ gem 'rspec-collection_matchers', '~> 1.2.0'
18
+ gem 'rspec-its', '~> 1.3.0'
19
+ gem 'rspec_junit_formatter', '~> 0.5.1'
20
+ gem 'rubocop', '~> 1.36.0'
21
+ gem 'simplecov', '~> 0.21.2'
22
+ gem 'webmock', '~> 3.18.1'
data/README.md CHANGED
@@ -1,17 +1,19 @@
1
1
  # Restforce
2
2
 
3
- [![CircleCI](https://circleci.com/gh/restforce/restforce.svg?style=svg)](https://circleci.com/gh/restforce/restforce) [![Code Climate](https://codeclimate.com/github/restforce/restforce.png)](https://codeclimate.com/github/restforce/restforce) [![Dependency Status](https://gemnasium.com/restforce/restforce.png)](https://gemnasium.com/restforce/restforce)
4
- ![](https://img.shields.io/gem/dt/restforce.svg)
3
+ [![CircleCI](https://circleci.com/gh/restforce/restforce.svg?style=svg)](https://circleci.com/gh/restforce/restforce)
4
+ ![Downloads](https://img.shields.io/gem/dt/restforce.svg)
5
5
 
6
6
  Restforce is a ruby gem for the [Salesforce REST api](http://www.salesforce.com/us/developer/docs/api_rest/index.htm).
7
7
 
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 orgs.
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](http://restforce.org/) | [Documentation](http://rubydoc.info/gems/restforce/frames) | [Changelog](https://github.com/restforce/restforce/tree/master/CHANGELOG.md)
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', '~> 4.2.0'
30
+ gem 'restforce', '~> 6.0.0'
29
31
 
30
32
  And then execute:
31
33
 
@@ -35,7 +37,14 @@ Or install it yourself as:
35
37
 
36
38
  $ gem install restforce
37
39
 
38
- __As of [version 4.0.0](https://github.com/restforce/restforce/blob/master/CHANGELOG.md#400-oct-9-2019), this gem is only compatible with Ruby 2.4.0 and later.__ You'll need to use version 3.2.0 or earlier if you're running on Ruby 2.3. If you're running on Ruby 2.2, 2.1 or 2.0, use version 2.5.3 or earlier. For Ruby 1.9.3, you'll need to manually specify that you wish to use version 2.4.2.
40
+ __As of version 6.0.0, this gem is only compatible with Ruby 2.7.0 and later.__ If you're using an earlier Ruby version:
41
+
42
+ * for Ruby 2.6, use version 5.3.1 or earlier
43
+ * for Ruby 2.5, use version 5.0.6 or earlier
44
+ * for Ruby 2.4, use version 4.3.0 or earlier
45
+ * for Ruby 2.3, use version 3.2.0 or earlier
46
+ * for Ruby versions 2.2, 2.1 and 2.0, use version 2.5.3 or earlier
47
+ * for Ruby 1.9.3, use version 2.4.2
39
48
 
40
49
  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
50
 
@@ -48,7 +57,7 @@ so you can do things like `client.query('select Id, (select Name from Children__
48
57
  ### Initialization
49
58
 
50
59
  Which authentication method you use really depends on your use case. If you're
51
- building an application where many users from different orgs are authenticated
60
+ building an application where many users from different organizations are authenticated
52
61
  through oauth and you need to interact with data in their org on their behalf,
53
62
  you should use the OAuth token authentication method.
54
63
 
@@ -78,7 +87,7 @@ client = Restforce.new(oauth_token: 'access_token',
78
87
  api_version: '41.0')
79
88
  ```
80
89
 
81
- The middleware will use the `refresh_token` automatically to acquire a new `access_token` if the existing `access_token` is invalid.
90
+ 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
91
 
83
92
  `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
93
 
@@ -142,7 +151,19 @@ export SALESFORCE_API_VERSION="41.0"
142
151
  client = Restforce.new
143
152
  ```
144
153
 
145
- ### Proxy Support
154
+ **Note:** Restforce library does not cache JWT Bearer tokens automatically. This means that every instantiation of the Restforce class will be treated as a new login by Salesforce. Remember that Salesforce enforces [rate limits on login requests](https://help.salesforce.com/s/articleView?id=000312767&type=1). If you are building an application that will instantiate the Restforce class more than this specified rate limit, you might want to consider caching the Bearer token either in-memory or in your own storage by leveraging the `authentication_callback` method.
155
+
156
+ #### Sandbox Organizations
157
+
158
+ You can connect to sandbox organizations by specifying a host. The default host is
159
+ 'login.salesforce.com':
160
+
161
+ ```ruby
162
+ client = Restforce.new(host: 'test.salesforce.com')
163
+ ```
164
+ The host can also be set with the environment variable `SALESFORCE_HOST`.
165
+
166
+ #### Proxy Support
146
167
 
147
168
  You can specify a HTTP proxy using the `proxy_uri` option, as follows, or by setting the `SALESFORCE_PROXY_URI` environment variable:
148
169
 
@@ -158,16 +179,6 @@ client = Restforce.new(username: 'foo',
158
179
 
159
180
  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
181
 
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
182
  #### Global configuration
172
183
 
173
184
  You can set any of the options passed into `Restforce.new` globally:
@@ -183,7 +194,7 @@ end
183
194
 
184
195
  By default, the gem defaults to using Version 26.0 (Winter '13) of the Salesforce API. This maintains backwards compatibility for existing users.
185
196
 
186
- __We strongly suggest configuring Restforce to use the most recent API version, currently Version 41.0 (Winter '18) to get the best Salesforce API experience__ - for example, some more recently-added API endpoints will not be available without moving to a more recent
197
+ __We strongly suggest configuring Restforce to use the [most recent API version](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_versions.htm), to get the best Salesforce API experience__ - for example, some more recently-added API endpoints will not be available without moving to a more recent
187
198
  version. If you're trying to use a method that is unavailable with your API version,
188
199
  Restforce will raise an `APIVersionError`.
189
200
 
@@ -285,6 +296,8 @@ client.find('Account', '1234', 'Some_External_Id_Field__c')
285
296
  # => #<Restforce::SObject Id="001D000000INjVe" Name="Test" LastModifiedBy="005G0000002f8FHIAY" ... >
286
297
  ```
287
298
 
299
+ `find` raises an error if nothing is found.
300
+
288
301
  ### select
289
302
 
290
303
  `select` allows the fetching of a specific list of fields from a single object. It requires an `external_id` lookup, but is often much faster than an arbitrary query.
@@ -328,8 +341,11 @@ client.update('Account', Id: '0016000000MRatd', Name: 'Whizbang Corp')
328
341
  ```ruby
329
342
  # Update the record with external `External__c` external ID set to '12'
330
343
  client.upsert('Account', 'External__c', External__c: 12, Name: 'Foobar')
344
+ # => true or "RecordId"
331
345
  ```
332
346
 
347
+ 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.
348
+
333
349
  ### destroy
334
350
 
335
351
  ```ruby
@@ -451,13 +467,13 @@ info.user_id
451
467
 
452
468
  ### File Uploads
453
469
 
454
- Using the new [Blob Data](http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_insert_update_blob.htm) api feature (500mb limit):
470
+ 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
471
 
456
472
  ```ruby
457
473
  client.create('Document', FolderId: '00lE0000000FJ6H',
458
474
  Description: 'Document test',
459
475
  Name: 'My image',
460
- Body: Restforce::UploadIO.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg')
476
+ Body: Restforce::FilePart.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg')
461
477
  ```
462
478
 
463
479
  Using base64 encoded data (37.5mb limit):
@@ -469,7 +485,7 @@ client.create('Document', FolderId: '00lE0000000FJ6H',
469
485
  Body: Base64::encode64(File.read('image.jpg'))
470
486
  ```
471
487
 
472
- _See also: [Inserting or updating blob data](http://www.salesforce.com/us/developer/docs/api_rest/Content/dome_sobject_insert_update_blob.htm)_
488
+ _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
489
 
474
490
  * * *
475
491
 
@@ -564,6 +580,52 @@ end
564
580
  Boom, you're now receiving push notifications when Accounts are
565
581
  created/updated.
566
582
 
583
+ #### Composite API
584
+
585
+ Restforce supports the [Composite API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_composite.htm).
586
+ This feature permits the user to send a composite object—that is, a complex
587
+ object with nested children—in a single API call. Up to 25 requests may be
588
+ included in a single composite.
589
+
590
+ Note that `GET` is not yet implemented for this API.
591
+
592
+ ```ruby
593
+ # build up an array of requests:
594
+ requests << {
595
+ method: :update,
596
+ sobject: sobject, # e.g. "Contact"
597
+ reference_id: reference_id,
598
+ data: data
599
+ }
600
+
601
+ # send every 25 requests as a subrequest in a single composite call
602
+ requests.each_slice(25).map do |req_slice|
603
+ client.composite do |subrequest|
604
+ req_slice.each do |r|
605
+ subrequest.send *r.values
606
+ end
607
+ end
608
+ end
609
+
610
+ # note that we're using `map` to return an array of each responses to each
611
+ # composite call; 100 requests will produce 4 responses
612
+ ```
613
+
614
+ #### Composite Batch API
615
+
616
+ Restforce supports the [Composite Batch API](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_batch.htm).
617
+ This feature permits up to 25 subrequests in a single request, though each
618
+ subrequest counts against the API limit. On the other hand, it has fewer
619
+ limitations than the Composite API.
620
+
621
+ ```
622
+ client.batch do |subrequests|
623
+ subrequests.create('Object', name: 'test')
624
+ subrequests.update('Object', id: '123', name: 'test')
625
+ subrequests.destroy('Object', '123')
626
+ end
627
+ ```
628
+
567
629
  #### Replaying Events
568
630
 
569
631
  Since API version 37.0, Salesforce stores events for 24 hours and they can be
@@ -688,7 +750,23 @@ client.without_caching do
688
750
  end
689
751
  ```
690
752
 
691
- Caching is done on based on your authentication credentials, so cached responses will not be shared between different Salesforce logins.
753
+ If you prefer to opt in to caching on a per-request, you can do so by using .with_caching and
754
+ setting the `use_cache` config option to false:
755
+
756
+ ```ruby
757
+ Restforce.configure do |config|
758
+ config.cache = Rails.cache
759
+ config.use_cache = false
760
+ end
761
+ ```
762
+
763
+ ```ruby
764
+ client.with_caching do
765
+ client.query('select Id from Account')
766
+ end
767
+ ```
768
+
769
+ Caching is done based on your authentication credentials, so cached responses will not be shared between different Salesforce logins.
692
770
 
693
771
  * * *
694
772
 
data/UPGRADING.md ADDED
@@ -0,0 +1,67 @@
1
+ # Upgrading from Restforce 5.x to 6.x
2
+
3
+ __There are two breaking changes introduced in Restforce 6.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
+ ## Versions of `faraday` before `v1.1.0` are no longer supported
6
+
7
+ __Likelyhood of impact__: Moderate
8
+
9
+ Restforce uses a gem called [`faraday`](https://github.com/lostisland/faraday) to make HTTP requests to Salesforce.
10
+
11
+ Up until now, Restforce has supported Faraday versions between v0.9.0 and v1.10.0.
12
+
13
+ In Restforce 6.x, we drop support for Faraday versions before v1.1.0, and add support for Faraday v2.x.
14
+
15
+ This will allow you to use the latest versions of Faraday and benefit from security patches, new features, etc., but you may need to adapt your code. The impact of this change will depend on your project:
16
+
17
+ * If Restforce is the only part of your project using Faraday - that is, your own code doesn't use Faraday and none of your other gems use Faraday - then you shouldn't need to do anything special. Just upgrade Restforce, and everything should be handled automatically.
18
+ * If your own code uses Faraday or another gem you use depends on Faraday, and you're currently using a Faraday version before v1.1.0, you will need to upgrade your Faraday version. If possible, you should upgrade to the latest version (v2.4.0 at the time of writing). This may require you to adapt your code (see [here](https://github.com/lostisland/faraday/blob/main/UPGRADING.md) for Faraday's instructions) or upgrade other gems you depend on.
19
+
20
+ ## Ruby 2.6 is no longer supported
21
+
22
+ __Likelyhood of impact__: Moderate
23
+
24
+ Ruby 2.6 is no longer officially supported as an active version of the Ruby language. That means that it will not receive patches and security fixes.
25
+
26
+ Accordingly, we've dropped support for Ruby 2.6 and earlier in the Restforce library. The gemspec now specifies that only 2.7 onwards is supported, and this will be enforced by RubyGems.
27
+
28
+ Before you update to Restforce 6.x, you'll need to switch to Ruby 2.7 or later. The current version of Ruby at the time of wriing is 3.1.
29
+
30
+ # Upgrading from Restforce 4.x to 5.x
31
+
32
+ __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.
33
+
34
+ ## Error classes are now defined up-front, rather than dynamically at runtime
35
+
36
+ __Likelyhood of impact__: Moderate
37
+
38
+ The Salesforce REST API can return a range of `errorCode`s representing different kinds of errors. To make these easy to
39
+ handle in your code, we want to turn these into individual, specific exception classes in the `Restforce::ErrorCode` namespace that inherit from `Restforce:: ResponseError`.
40
+
41
+ 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.
42
+
43
+ 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`).
44
+
45
+ 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).
46
+
47
+ ## Ruby 2.4 is no longer supported
48
+
49
+ __Likelyhood of impact__: Moderate
50
+
51
+ 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.
52
+
53
+ 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.
54
+
55
+ 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.
56
+
57
+ ## `Restforce::UnauthorizedError` no longer inherits from `Restforce::Error`
58
+
59
+ __Likelyhood of impact__: Low
60
+
61
+ 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.
62
+
63
+ 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.
64
+
65
+ If you refer to `Restforce::Error` anywhere in your code, you should check whether you also need to take into account `Restforce::UnauthorizedError`.
66
+
67
+ 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.
@@ -0,0 +1,7 @@
1
+ version: "3.6"
2
+ services:
3
+ restforce:
4
+ build: .
5
+ image: restforce:dev
6
+ volumes:
7
+ - .:/srv
@@ -8,5 +8,6 @@ module Restforce
8
8
  include Restforce::Concerns::Caching
9
9
  include Restforce::Concerns::API
10
10
  include Restforce::Concerns::BatchAPI
11
+ include Restforce::Concerns::CompositeAPI
11
12
  end
12
13
  end