restforce 5.0.5 → 5.2.0

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