restforce 4.0.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +9 -9
  3. data/.github/ISSUE_TEMPLATE/unhandled-salesforce-error.md +17 -0
  4. data/.rubocop.yml +4 -3
  5. data/.rubocop_todo.yml +2 -2
  6. data/CHANGELOG.md +36 -0
  7. data/CONTRIBUTING.md +1 -1
  8. data/Gemfile +1 -1
  9. data/README.md +71 -33
  10. data/UPGRADING.md +38 -0
  11. data/lib/restforce.rb +11 -13
  12. data/lib/restforce/collection.rb +5 -0
  13. data/lib/restforce/concerns/api.rb +1 -1
  14. data/lib/restforce/concerns/authentication.rb +10 -0
  15. data/lib/restforce/concerns/base.rb +2 -0
  16. data/lib/restforce/concerns/caching.rb +7 -0
  17. data/lib/restforce/concerns/connection.rb +3 -3
  18. data/lib/restforce/concerns/streaming.rb +22 -7
  19. data/lib/restforce/config.rb +6 -0
  20. data/lib/restforce/error_code.rb +406 -0
  21. data/lib/restforce/file_part.rb +24 -0
  22. data/lib/restforce/mash.rb +1 -1
  23. data/lib/restforce/middleware/authentication.rb +7 -3
  24. data/lib/restforce/middleware/authentication/jwt_bearer.rb +38 -0
  25. data/lib/restforce/middleware/caching.rb +1 -1
  26. data/lib/restforce/middleware/instance_url.rb +1 -1
  27. data/lib/restforce/middleware/raise_error.rb +3 -4
  28. data/lib/restforce/version.rb +1 -1
  29. data/restforce.gemspec +14 -14
  30. data/spec/fixtures/test_private.key +27 -0
  31. data/spec/integration/abstract_client_spec.rb +18 -6
  32. data/spec/spec_helper.rb +14 -1
  33. data/spec/support/fixture_helpers.rb +1 -3
  34. data/spec/unit/collection_spec.rb +18 -0
  35. data/spec/unit/concerns/api_spec.rb +1 -1
  36. data/spec/unit/concerns/authentication_spec.rb +35 -0
  37. data/spec/unit/concerns/caching_spec.rb +26 -0
  38. data/spec/unit/concerns/connection_spec.rb +2 -2
  39. data/spec/unit/concerns/streaming_spec.rb +58 -30
  40. data/spec/unit/error_code_spec.rb +61 -0
  41. data/spec/unit/mash_spec.rb +5 -0
  42. data/spec/unit/middleware/authentication/jwt_bearer_spec.rb +62 -0
  43. data/spec/unit/middleware/authentication_spec.rb +27 -4
  44. data/spec/unit/middleware/raise_error_spec.rb +19 -10
  45. data/spec/unit/signed_request_spec.rb +1 -1
  46. data/spec/unit/sobject_spec.rb +2 -5
  47. metadata +41 -31
  48. data/lib/restforce/upload_io.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e4311062c172c1fd0706872045d29fed90d5b36df5f6c2656d88c37ac680fb2
4
- data.tar.gz: f8b6e07bd7533342229f0bb02ef00a731dda64990927bc2c8d822fbfa46f5a29
3
+ metadata.gz: c668433781a24af5211bf9c102e5601ef69919a856928fb4a876de43bb96fa14
4
+ data.tar.gz: 5d5ee573dc491e1eb38703028d2c107d28a9fa2b37616f08e3004cc20c653868
5
5
  SHA512:
6
- metadata.gz: 33d02a24a1fc9e7efd40a318f75a48992215b759bcb33c8860a0e4e49fbc5a2eac13cce908dac4605164af58fa6e43473b753668926e0875deeba63eac4cc51c
7
- data.tar.gz: 1a6155b0ec55633ebf061e7e709b7e391fe266563f5476b658040139e977ea00baf356602aacf8c5b2aef313c0b48296bfad984d444fe437249424810b567512
6
+ metadata.gz: f938c2e517cb05c33c4526c04c0384edaa70f39bed1a391a58032fb52574fd50c20fab21f859439957070506d4c03d84447134885e14d5ad59f3bff02f689545
7
+ data.tar.gz: f2c466b8d4ae41bc6519dfaa27dbdbae2e302ad99c1ca52456f94bc391f243f99037bad48fc58533b83bb9cb146a30580e0cbe79a91cd9872e70fd0c9775865d
@@ -34,23 +34,23 @@ references:
34
34
  destination: test-results
35
35
 
36
36
  jobs:
37
- build-ruby265:
37
+ build-ruby271:
38
38
  docker:
39
- - image: circleci/ruby:2.6.5
39
+ - image: circleci/ruby:2.7.1
40
40
  steps: *steps
41
- build-ruby257:
41
+ build-ruby266:
42
42
  docker:
43
- - image: circleci/ruby:2.5.7
43
+ - image: circleci/ruby:2.6.6
44
44
  steps: *steps
45
- build-ruby249:
45
+ build-ruby258:
46
46
  docker:
47
- - image: circleci/ruby:2.4.9
47
+ - image: circleci/ruby:2.5.8
48
48
  steps: *steps
49
49
 
50
50
  workflows:
51
51
  version: 2
52
52
  tests:
53
53
  jobs:
54
- - build-ruby265
55
- - build-ruby257
56
- - build-ruby249
54
+ - build-ruby271
55
+ - build-ruby266
56
+ - build-ruby258
@@ -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
@@ -7,10 +7,11 @@ AllCops:
7
7
  Exclude:
8
8
  - .*/**/*
9
9
  - vendor/**/*
10
- TargetRubyVersion: 2.4
10
+ NewCops: enable
11
+ TargetRubyVersion: 2.5
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:
@@ -12,7 +12,7 @@
12
12
  # SupportedHashRocketStyles: key, separator, table
13
13
  # SupportedColonStyles: key, separator, table
14
14
  # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
15
- Layout/AlignHash:
15
+ Layout/HashAlignment:
16
16
  Exclude:
17
17
  - 'lib/restforce/middleware/logger.rb'
18
18
  - 'restforce.gemspec'
@@ -23,7 +23,7 @@ Layout/AlignHash:
23
23
  # Cop supports --auto-correct.
24
24
  # Configuration parameters: EnforcedStyle, IndentationWidth.
25
25
  # SupportedStyles: special_inside_parentheses, consistent, align_braces
26
- Layout/IndentFirstHashElement:
26
+ Layout/FirstHashElementIndentation:
27
27
  Exclude:
28
28
  - 'lib/restforce/concerns/connection.rb'
29
29
 
@@ -1,3 +1,39 @@
1
+ ## 5.0.0 (Jul 10, 2020)
2
+
3
+ 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.
4
+
5
+ ### Breaking changes
6
+
7
+ * __⚠️ 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).
8
+ * __⚠️ 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)
9
+ * __⚠️ 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).
10
+
11
+ ### Non-breaking changes
12
+
13
+ * Add support for `lostisland/faraday` v1.x, whilst maintaining support for v0.9.x (@ryansch)
14
+ * Add `#empty?` method to `Restforce::Collection`, returning whether they are any items in a collection (@bubaflub)
15
+ * Allow opting-in to caching on a per-call basis with `Restforce::Client#with_caching` (@swaincreates)
16
+ * Expose the response body from Salesforce on `Restforce::UnauthorizedError` and `Restforce::NotFoundError` (@michaeldbianchi)
17
+ * Remove the unnecessary depending on the `json` gem, which has been part of the Ruby standard library since v1.9 (@vonTronje)
18
+
19
+
20
+ ## 4.2.2 (Jan 23, 2020)
21
+
22
+ * Fix `NoMethodError: undefined method '[]' for nil:NilClass` error when generating objects to return (@apurkiss)
23
+
24
+ ## 4.2.1 (Dec 4, 2019)
25
+
26
+ * Handle empty response bodies returned with authentication errors (@sylvandor)
27
+ * Fix Faraday deprecation warning in newer Faraday versions (`v0.17.1` onwards) caused by inheriting from a deprecated class
28
+
29
+ ## 4.2.0 (Oct 23, 2019)
30
+
31
+ * Add support for platform events, CDC, generic events, etc. in the Streaming API (@nathanKramer)
32
+
33
+ ## 4.1.0 (Oct 20, 2019)
34
+
35
+ * Add support for JWT authentication (@nathanKramer, @tagCincy)
36
+
1
37
  ## 4.0.0 (Oct 9, 2019)
2
38
 
3
39
  * __Deprecate support for Ruby 2.3__, since [Ruby 2.3 reached its end-of-life](https://www.ruby-lang.org/en/news/2019/03/31/support-of-ruby-2-3-has-ended/) in March 2019. (This is the only breaking change included in this version.)
@@ -34,4 +34,4 @@ 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).*
data/Gemfile CHANGED
@@ -3,8 +3,8 @@
3
3
  source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
- gem 'faraday', '~> 0.17.0'
7
6
  gem 'jruby-openssl', platforms: :jruby
7
+ gem 'jwt'
8
8
  gem 'rake'
9
9
 
10
10
  group :development do
data/README.md CHANGED
@@ -8,7 +8,7 @@ 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 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)
@@ -19,13 +19,13 @@ Features include:
19
19
  * Support for dependent picklists.
20
20
  * Support for decoding [Force.com Canvas](http://www.salesforce.com/us/developer/docs/platform_connectpre/canvas_framework.pdf) signed requests. (NEW!)
21
21
 
22
- [Official Website](http://restforce.org/) | [Documentation](http://rubydoc.info/gems/restforce/frames) | [Changelog](https://github.com/restforce/restforce/tree/master/CHANGELOG.md)
22
+ [Official Website](https://restforce.github.io/) | [Documentation](http://rubydoc.info/gems/restforce/frames) | [Changelog](https://github.com/restforce/restforce/tree/master/CHANGELOG.md)
23
23
 
24
24
  ## Installation
25
25
 
26
26
  Add this line to your application's Gemfile:
27
27
 
28
- gem 'restforce', '~> 4.0.0'
28
+ gem 'restforce', '~> 5.0.0'
29
29
 
30
30
  And then execute:
31
31
 
@@ -35,7 +35,12 @@ Or install it yourself as:
35
35
 
36
36
  $ gem install restforce
37
37
 
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.
38
+ __As of version 5.0.0, this gem is only compatible with Ruby 2.5.0 and later.__ If you're using an earlier Ruby version:
39
+
40
+ * for Ruby 2.4, use version 4.2.2 or earlier
41
+ * for Ruby 2.3, use version 3.2.0 or earlier
42
+ * for Ruby versions 2.2, 2.1 and 2.0, use version 2.5.3 or earlier
43
+ * for Ruby 1.9.3, use version 2.4.2
39
44
 
40
45
  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
46
 
@@ -48,7 +53,7 @@ so you can do things like `client.query('select Id, (select Name from Children__
48
53
  ### Initialization
49
54
 
50
55
  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
56
+ building an application where many users from different organizations are authenticated
52
57
  through oauth and you need to interact with data in their org on their behalf,
53
58
  you should use the OAuth token authentication method.
54
59
 
@@ -78,7 +83,7 @@ client = Restforce.new(oauth_token: 'access_token',
78
83
  api_version: '41.0')
79
84
  ```
80
85
 
81
- The middleware will use the `refresh_token` automatically to acquire a new `access_token` if the existing `access_token` is invalid.
86
+ 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
87
 
83
88
  `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
89
 
@@ -111,6 +116,21 @@ client = Restforce.new(username: 'foo',
111
116
  api_version: '41.0')
112
117
  ```
113
118
 
119
+ #### JWT Bearer Token
120
+
121
+ If you prefer to use a [JWT Bearer Token](https://developer.salesforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com#Obtaining_an_Access_Token_using_a_JWT_Bearer_Token) to authenticate:
122
+
123
+ ```ruby
124
+ client = Restforce.new(username: 'foo',
125
+ client_id: 'client_id',
126
+ instance_url: 'instance_url',
127
+ jwt_key: 'certificate_private_key',
128
+ api_version: '38.0')
129
+ ```
130
+
131
+ The `jwt_key` option is the private key of the certificate uploaded to your Connected App in Salesforce.
132
+ Choose "use digital signatures" in the Connected App configuration screen to upload your certificate.
133
+
114
134
  You can also set the username, password, security token, client ID, client
115
135
  secret and API version in environment variables:
116
136
 
@@ -127,7 +147,17 @@ export SALESFORCE_API_VERSION="41.0"
127
147
  client = Restforce.new
128
148
  ```
129
149
 
130
- ### Proxy Support
150
+ #### Sandbox Organizations
151
+
152
+ You can connect to sandbox organizations by specifying a host. The default host is
153
+ 'login.salesforce.com':
154
+
155
+ ```ruby
156
+ client = Restforce.new(host: 'test.salesforce.com')
157
+ ```
158
+ The host can also be set with the environment variable `SALESFORCE_HOST`.
159
+
160
+ #### Proxy Support
131
161
 
132
162
  You can specify a HTTP proxy using the `proxy_uri` option, as follows, or by setting the `SALESFORCE_PROXY_URI` environment variable:
133
163
 
@@ -143,16 +173,6 @@ client = Restforce.new(username: 'foo',
143
173
 
144
174
  You may specify a username and password for the proxy with a URL along the lines of 'http://user:password@proxy.example.com:123'.
145
175
 
146
- #### Sandbox Orgs
147
-
148
- You can connect to sandbox orgs by specifying a host. The default host is
149
- 'login.salesforce.com':
150
-
151
- ```ruby
152
- client = Restforce.new(host: 'test.salesforce.com')
153
- ```
154
- The host can also be set with the environment variable `SALESFORCE_HOST`.
155
-
156
176
  #### Global configuration
157
177
 
158
178
  You can set any of the options passed into `Restforce.new` globally:
@@ -442,7 +462,7 @@ Using the new [Blob Data](http://www.salesforce.com/us/developer/docs/api_rest/C
442
462
  client.create('Document', FolderId: '00lE0000000FJ6H',
443
463
  Description: 'Document test',
444
464
  Name: 'My image',
445
- Body: Restforce::UploadIO.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg')
465
+ Body: Restforce::FilePart.new(File.expand_path('image.jpg', __FILE__), 'image/jpeg')
446
466
  ```
447
467
 
448
468
  Using base64 encoded data (37.5mb limit):
@@ -473,11 +493,11 @@ document = client.query('select Id, Name, Body from Document').first
473
493
  File.open(document.Name, 'wb') { |f| f.write(document.Body) }
474
494
  ```
475
495
 
476
- **Note:** The example above is only applicable if your SOQL query returns a single Document record. If more than one record is returned,
496
+ **Note:** The example above is only applicable if your SOQL query returns a single Document record. If more than one record is returned,
477
497
  the Body field contains an URL to retrieve the BLOB content for the first 2000 records returned. Subsequent records contain the BLOB content
478
- in the Body field. This is confusing and hard to debug. See notes in [Issue #301](https://github.com/restforce/restforce/issues/301#issuecomment-298972959) explaining this detail.
479
- **Executive Summary:** Don't retrieve the Body field in a SOQL query; instead, use the BLOB retrieval URL documented
480
- in [SObject BLOB Retrieve](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_sobject_blob_retrieve.htm)
498
+ in the Body field. This is confusing and hard to debug. See notes in [Issue #301](https://github.com/restforce/restforce/issues/301#issuecomment-298972959) explaining this detail.
499
+ **Executive Summary:** Don't retrieve the Body field in a SOQL query; instead, use the BLOB retrieval URL documented
500
+ in [SObject BLOB Retrieve](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_sobject_blob_retrieve.htm)
481
501
 
482
502
  * * *
483
503
 
@@ -513,8 +533,10 @@ client.get('/services/apexrest/FieldCase', company: 'GenePoint')
513
533
 
514
534
  ### Streaming
515
535
 
516
- Restforce supports the [Streaming API](http://wiki.developerforce.com/page/Getting_Started_with_the_Force.com_Streaming_API), and makes implementing
517
- pub/sub with Salesforce a trivial task:
536
+ Restforce supports the [Streaming API](https://trailhead.salesforce.com/en/content/learn/modules/api_basics/api_basics_streaming), and makes implementing
537
+ pub/sub with Salesforce a trivial task.
538
+
539
+ Here is an example of creating and subscribing to a `PushTopic`:
518
540
 
519
541
  ```ruby
520
542
  # Restforce uses faye as the underlying implementation for CometD.
@@ -538,7 +560,7 @@ client.create!('PushTopic',
538
560
 
539
561
  EM.run do
540
562
  # Subscribe to the PushTopic.
541
- client.subscribe 'AllAccounts' do |message|
563
+ client.subscription '/topic/AllAccounts' do |message|
542
564
  puts message.inspect
543
565
  end
544
566
  end
@@ -559,7 +581,7 @@ that event ID:
559
581
  ```ruby
560
582
  EM.run {
561
583
  # Subscribe to the PushTopic.
562
- client.subscribe 'AllAccounts', replay: 10 do |message|
584
+ client.subscription '/topic/AllAccounts', replay: 10 do |message|
563
585
  puts message.inspect
564
586
  end
565
587
  }
@@ -574,14 +596,14 @@ There are two magic values for the replay ID accepted by Salesforce:
574
596
 
575
597
  **Warning**: Only use a replay ID of a event from the last 24 hours otherwise
576
598
  Salesforce will not send anything, including newer events. If in doubt, use one
577
- of the two magic replay IDs mentioned above.
599
+ of the two magic replay IDs mentioned above.
578
600
 
579
- You might want to store the replay ID in some sort of datastore so you can
601
+ You might want to store the replay ID in some sort of datastore so you can
580
602
  access it, for example between application restarts. In that case, there is the
581
603
  option of passing a custom replay handler which responds to `[]` and `[]=`.
582
604
 
583
605
  Below is a sample replay handler that stores the replay ID for each channel in
584
- memory using a Hash, stores a timestamp and has some rudimentary logic that
606
+ memory using a Hash, stores a timestamp and has some rudimentary logic that
585
607
  will use one of the magic IDs depending on the value of the timestamp:
586
608
 
587
609
  ```ruby
@@ -633,13 +655,13 @@ of the subscription:
633
655
  EM.run {
634
656
  # Subscribe to the PushTopic and use the custom replay handler to store any
635
657
  # received replay ID.
636
- client.subscribe 'AllAccounts', replay: SimpleReplayHandler.new do |message|
658
+ client.subscription '/topic/AllAccounts', replay: SimpleReplayHandler.new do |message|
637
659
  puts message.inspect
638
660
  end
639
661
  }
640
- ```
662
+ ```
641
663
 
642
- _See also_:
664
+ _See also_:
643
665
 
644
666
  * [Force.com Streaming API docs](http://www.salesforce.com/us/developer/docs/api_streaming/index.htm)
645
667
  * [Message Durability docs](https://developer.salesforce.com/docs/atlas.en-us.api_streaming.meta/api_streaming/using_streaming_api_durability.htm)
@@ -671,7 +693,23 @@ client.without_caching do
671
693
  end
672
694
  ```
673
695
 
674
- Caching is done on based on your authentication credentials, so cached responses will not be shared between different Salesforce logins.
696
+ If you prefer to opt in to caching on a per-request, you can do so by using .with_caching and
697
+ setting the `use_cache` config option to false:
698
+
699
+ ```ruby
700
+ Restforce.configure do |config|
701
+ config.cache = Rails.cache
702
+ config.use_cache = false
703
+ end
704
+ ```
705
+
706
+ ```ruby
707
+ client.with_caching do
708
+ client.query('select Id from Account')
709
+ end
710
+ ```
711
+
712
+ Caching is done based on your authentication credentials, so cached responses will not be shared between different Salesforce logins.
675
713
 
676
714
  * * *
677
715
 
@@ -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.
@@ -3,6 +3,7 @@
3
3
  require 'faraday'
4
4
  require 'faraday_middleware'
5
5
  require 'json'
6
+ require 'jwt'
6
7
 
7
8
  require 'restforce/version'
8
9
  require 'restforce/config'
@@ -14,7 +15,8 @@ module Restforce
14
15
  autoload :Middleware, 'restforce/middleware'
15
16
  autoload :Attachment, 'restforce/attachment'
16
17
  autoload :Document, 'restforce/document'
17
- autoload :UploadIO, 'restforce/upload_io'
18
+ autoload :FilePart, 'restforce/file_part'
19
+ autoload :UploadIO, 'restforce/file_part' # Deprecated
18
20
  autoload :SObject, 'restforce/sobject'
19
21
  autoload :Client, 'restforce/client'
20
22
  autoload :Mash, 'restforce/mash'
@@ -43,27 +45,23 @@ module Restforce
43
45
  Error = Class.new(StandardError)
44
46
  ServerError = Class.new(Error)
45
47
  AuthenticationError = Class.new(Error)
46
- UnauthorizedError = Class.new(Error)
48
+ UnauthorizedError = Class.new(Faraday::ClientError)
47
49
  APIVersionError = Class.new(Error)
48
50
  BatchAPIError = Class.new(Error)
49
51
 
50
- # Inherit from Faraday::Error::ResourceNotFound for backwards-compatibility
51
- # Consumers of this library that rescue and handle Faraday::Error::ResourceNotFound
52
+ # Inherit from Faraday::ResourceNotFound for backwards-compatibility
53
+ # Consumers of this library that rescue and handle Faraday::ResourceNotFound
52
54
  # can continue to do so.
53
- NotFoundError = Class.new(Faraday::Error::ResourceNotFound)
55
+ NotFoundError = Class.new(Faraday::ResourceNotFound)
54
56
 
55
- # Inherit from Faraday::Error::ClientError for backwards-compatibility
56
- # Consumers of this library that rescue and handle Faraday::Error::ClientError
57
+ # Inherit from Faraday::ClientError for backwards-compatibility
58
+ # Consumers of this library that rescue and handle Faraday::ClientError
57
59
  # can continue to do so.
58
- ResponseError = Class.new(Faraday::Error::ClientError)
60
+ ResponseError = Class.new(Faraday::ClientError)
59
61
  MatchesMultipleError= Class.new(ResponseError)
60
62
  EntityTooLargeError = Class.new(ResponseError)
61
63
 
62
- module ErrorCode
63
- def self.const_missing(constant_name)
64
- const_set constant_name, Class.new(ResponseError)
65
- end
66
- end
64
+ require 'restforce/error_code'
67
65
 
68
66
  class << self
69
67
  # Alias for Restforce::Data::Client.new