restforce 5.0.6 → 5.2.1

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: 6644bf699621fb5414dce1dce275e5a265fca50305bcfca98864b6c1683f1687
4
- data.tar.gz: 5ef0177a3a91dbe1637fc493b7f0bc478fca34c49e392abb1eccdf8bf951aa66
3
+ metadata.gz: 891d81fbf377945b09db6058467d21da1720d985e70ad060e4bcbe35d5efc9f6
4
+ data.tar.gz: 2ce207d94d49504e28680d7b854633cc3c2c0b329ed23b04769528799b71785e
5
5
  SHA512:
6
- metadata.gz: 7c7d3e8b58743f8d4ae6ae9255c2d89cc78b06a5e963350784ff3c884396bf1ef03fb986f2aba7bd231d8ae9af2f0b2af78a77c98fcb62356ac09b1411753e13
7
- data.tar.gz: 5c8bb85fdcd28e5eba8d0939ef1868d42b99d079cddd056941ec7c4cf591d3789caa2b569cafeb8415a89755e567de1a93486dc9c18c5507275adad5631374cc
6
+ metadata.gz: 04e9f867ebadf6a8d61ffad3ebdb14b9924011df9b408efb9f17bb8a65c7ad5a4de1caa18b78dd365b889bf6b32801d7c30d7de02f105be38a3b4111cf83b792
7
+ data.tar.gz: c72397f42ef4a4f95a053557bf8971e3eeff78994b21ccdc232638ef1847c08e7e1c8e9e33f6055725c9fbc57755de85d474cf6063094ec6e33e211a93ba14d4
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
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,25 @@
1
+ # 5.2.1 (Dec 8, 2021)
2
+
3
+ * Handle the `OPERATION_TOO_LARGE` error returned by Salesforce (@timrogers)
4
+ * Handle the `INVALID_SIGNUP_COUNTRY` error returned by Salesforce (@timrogers)
5
+
6
+ ## 5.2.0 (Oct 15, 2021)
7
+
8
+ * Add support for Salesforce's Composite API and Composite Batch API (@meenie, @amacdougall)
9
+ * Improve the performance of counting numbers of query results with `Restforce::Collection#count`, avoiding unnecessary API requests (@jhass)
10
+
11
+ ## 5.1.1 (Oct 13, 2021)
12
+
13
+ * Handle the `INVALID_REPLICATION_DATE` error returned by Salesforce (@michaelwnyc)
14
+ * Handle the `BIG_OBJECT_UNSUPPORTED_OPERATION` error returned by Salesforce (@remon)
15
+
16
+ ## 5.1.0 (Aug 26, 2021)
17
+
18
+ * Add official support for Ruby 3.0 (@timrogers)
19
+ * Drop support for Ruby 2.5, which has reached end-of-life (@timrogers)
20
+ * Handle the `QUERY_TIMEOUT` error returned by Salesforce (@timrogers)
21
+ * Remove unnecessary development dependencies for the gem, which can just be in the project's `Gemfile` (@timrogers)
22
+
1
23
  ## 5.0.6 (Jun 17, 2021)
2
24
 
3
25
  * Handle the `API_DISABLED_FOR_ORG` error returned by Salesforce (@cmac)
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.23.0'
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.6'
30
+ gem 'restforce', '~> 5.2.1'
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
@@ -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
@@ -31,6 +31,8 @@ module Restforce
31
31
 
32
32
  class BccSelfNotAllowedIfBccComplianceEnabled < ResponseError; end
33
33
 
34
+ class BigObjectUnsupportedOperation < ResponseError; end
35
+
34
36
  class CannotCascadeProductActive < ResponseError; end
35
37
 
36
38
  class CannotChangeFieldTypeOfApexReferencedField < ResponseError; end
@@ -237,10 +239,14 @@ module Restforce
237
239
 
238
240
  class InvalidReadOnlyUserDml < ResponseError; end
239
241
 
242
+ class InvalidReplicationDate < ResponseError; end
243
+
240
244
  class InvalidSaveAsActivityFlag < ResponseError; end
241
245
 
242
246
  class InvalidSessionId < ResponseError; end
243
247
 
248
+ class InvalidSignupCountry < ResponseError; end
249
+
244
250
  class InvalidStatus < ResponseError; end
245
251
 
246
252
  class InvalidType < ResponseError; end
@@ -327,6 +333,8 @@ module Restforce
327
333
 
328
334
  class OpWithInvalidUserTypeException < ResponseError; end
329
335
 
336
+ class OperationTooLarge < ResponseError; end
337
+
330
338
  class OptedOutOfMassMail < ResponseError; end
331
339
 
332
340
  class PackageLicenseRequired < ResponseError; end
@@ -341,6 +349,8 @@ module Restforce
341
349
 
342
350
  class PrivateContactOnAsset < ResponseError; end
343
351
 
352
+ class QueryTimeout < ResponseError; end
353
+
344
354
  class RecordInUseByWorkflow < ResponseError; end
345
355
 
346
356
  class RequestLimitExceeded < ResponseError; end
@@ -411,6 +421,7 @@ module Restforce
411
421
  BccNotAllowedIfBccComplianceEnabled,
412
422
  "BCC_SELF_NOT_ALLOWED_IF_BCC_COMPLIANCE_ENABLED" =>
413
423
  BccSelfNotAllowedIfBccComplianceEnabled,
424
+ "BIG_OBJECT_UNSUPPORTED_OPERATION" => BigObjectUnsupportedOperation,
414
425
  "CANNOT_CASCADE_PRODUCT_ACTIVE" => CannotCascadeProductActive,
415
426
  "CANNOT_CHANGE_FIELD_TYPE_OF_APEX_REFERENCED_FIELD" =>
416
427
  CannotChangeFieldTypeOfApexReferencedField,
@@ -521,8 +532,10 @@ module Restforce
521
532
  "INVALID_PARTNER_NETWORK_STATUS" => InvalidPartnerNetworkStatus,
522
533
  "INVALID_PERSON_ACCOUNT_OPERATION" => InvalidPersonAccountOperation,
523
534
  "INVALID_READ_ONLY_USER_DML" => InvalidReadOnlyUserDml,
535
+ "INVALID_REPLICATION_DATE" => InvalidReplicationDate,
524
536
  "INVALID_SAVE_AS_ACTIVITY_FLAG" => InvalidSaveAsActivityFlag,
525
537
  "INVALID_SESSION_ID" => InvalidSessionId,
538
+ "INVALID_SIGNUP_COUNTRY" => InvalidSignupCountry,
526
539
  "INVALID_STATUS" => InvalidStatus,
527
540
  "INVALID_TYPE" => InvalidType,
528
541
  "INVALID_TYPE_FOR_OPERATION" => InvalidTypeForOperation,
@@ -566,6 +579,7 @@ module Restforce
566
579
  "NUMBER_OUTSIDE_VALID_RANGE" => NumberOutsideValidRange,
567
580
  "NUM_HISTORY_FIELDS_BY_SOBJECT_EXCEEDED" => NumHistoryFieldsBySobjectExceeded,
568
581
  "OP_WITH_INVALID_USER_TYPE_EXCEPTION" => OpWithInvalidUserTypeException,
582
+ "OPERATION_TOO_LARGE" => OperationTooLarge,
569
583
  "OPTED_OUT_OF_MASS_MAIL" => OptedOutOfMassMail,
570
584
  "PACKAGE_LICENSE_REQUIRED" => PackageLicenseRequired,
571
585
  "PLATFORM_EVENT_ENCRYPTION_ERROR" => PlatformEventEncryptionError,
@@ -573,6 +587,7 @@ module Restforce
573
587
  "PLATFORM_EVENT_PUBLISH_FAILED" => PlatformEventPublishFailed,
574
588
  "PORTAL_USER_ALREADY_EXISTS_FOR_CONTACT" => PortalUserAlreadyExistsForContact,
575
589
  "PRIVATE_CONTACT_ON_ASSET" => PrivateContactOnAsset,
590
+ "QUERY_TIMEOUT" => QueryTimeout,
576
591
  "RECORD_IN_USE_BY_WORKFLOW" => RecordInUseByWorkflow,
577
592
  "REQUEST_LIMIT_EXCEEDED" => RequestLimitExceeded,
578
593
  "REQUEST_RUNNING_TOO_LONG" => RequestRunningTooLong,
@@ -606,9 +621,9 @@ module Restforce
606
621
  def self.get_exception_class(error_code)
607
622
  ERROR_EXCEPTION_CLASSES.fetch(error_code) do |_|
608
623
  warn "[restforce] An unrecognised error code, `#{error_code}` has been " \
609
- "received from Salesforce. Instead of raising an error-specific exception, " \
610
- "we'll raise a generic `ResponseError`. Please report this missing error code" \
611
- " on GitHub at <#{GITHUB_ISSUE_URL}>."
624
+ "received from Salesforce. Instead of raising an error-specific exception" \
625
+ ", we'll raise a generic `ResponseError`. Please report this missing " \
626
+ "error code on GitHub at <#{GITHUB_ISSUE_URL}>."
612
627
 
613
628
  # If we've received an unexpected error where we don't have a specific
614
629
  # class defined, we can return a generic ResponseError instead
@@ -618,10 +633,10 @@ module Restforce
618
633
 
619
634
  def self.const_missing(constant_name)
620
635
  warn "[restforce] You're referring to a Restforce error that isn't defined, " \
621
- "`#{name}::#{constant_name}` (for example by trying to `rescue` it). This might " \
622
- "be our fault - we've recently made some changes to how errors are defined. If " \
623
- "you're sure that this is a valid Salesforce error, then please create an " \
624
- "issue on GitHub at <#{GITHUB_ISSUE_URL}>."
636
+ "`#{name}::#{constant_name}` (for example by trying to `rescue` it). This " \
637
+ "might be our fault - we've recently made some changes to how errors are " \
638
+ "defined. If you're sure that this is a valid Salesforce error, then " \
639
+ "please create an issue on GitHub at <#{GITHUB_ISSUE_URL}>."
625
640
 
626
641
  super(constant_name)
627
642
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Restforce
4
- VERSION = '5.0.6'
4
+ VERSION = '5.2.1'
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
@@ -19,23 +19,14 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.metadata = {
21
21
  'source_code_uri' => 'https://github.com/restforce/restforce',
22
- 'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md'
22
+ 'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md',
23
+ 'rubygems_mfa_required' => 'true'
23
24
  }
24
25
 
25
- gem.required_ruby_version = '>= 2.5'
26
+ gem.required_ruby_version = '>= 2.6'
26
27
 
27
28
  gem.add_dependency 'faraday', '<= 2.0', '>= 0.9.0'
28
29
  gem.add_dependency 'faraday_middleware', ['>= 0.8.8', '<= 2.0']
29
-
30
+ gem.add_dependency 'hashie', '>= 1.2.0', '< 6.0'
30
31
  gem.add_dependency 'jwt', ['>= 1.5.6']
31
-
32
- 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.17.0'
39
- gem.add_development_dependency 'simplecov', '~> 0.21.2'
40
- gem.add_development_dependency 'webmock', '~> 3.13.0'
41
32
  end
@@ -129,18 +129,15 @@ shared_examples_for Restforce::AbstractClient do
129
129
  JSON.parse(fixture('sobject/delete_error_response'))
130
130
  end
131
131
 
132
- subject do
133
- lambda do
134
- client.update!('Account', Id: '001D000000INjVe', Name: 'Foobar')
135
- end
136
- end
132
+ it "raises Faraday::ResourceNotFound" do
133
+ expect { client.update!('Account', Id: '001D000000INjVe', Name: 'Foobar') }.
134
+ to raise_error do |exception|
135
+ expect(exception).to be_a(Faraday::ResourceNotFound)
137
136
 
138
- it {
139
- should raise_error(
140
- Faraday::ResourceNotFound,
141
- "#{error.first['errorCode']}: #{error.first['message']}"
142
- )
143
- }
137
+ expect(exception.message).
138
+ to start_with("#{error.first['errorCode']}: #{error.first['message']}")
139
+ end
140
+ end
144
141
  end
145
142
  end
146
143
 
@@ -158,7 +155,7 @@ shared_examples_for Restforce::AbstractClient do
158
155
  fixture: 'sobject/delete_error_response'
159
156
 
160
157
  subject { client.update('Account', Id: '001D000000INjVe', Name: 'Foobar') }
161
- it { should be_false }
158
+ it { should be false }
162
159
  end
163
160
 
164
161
  context 'with success' do
@@ -172,7 +169,7 @@ shared_examples_for Restforce::AbstractClient do
172
169
  client.update('Account', key => '001D000000INjVe', :Name => 'Foobar')
173
170
  end
174
171
 
175
- it { should be_true }
172
+ it { should be true }
176
173
  end
177
174
  end
178
175
  end
@@ -191,7 +188,7 @@ shared_examples_for Restforce::AbstractClient do
191
188
  Name: 'Foobar')
192
189
  end
193
190
 
194
- it { should be_true }
191
+ it { should be true }
195
192
  end
196
193
 
197
194
  context 'with string external Id key' do
@@ -200,7 +197,7 @@ shared_examples_for Restforce::AbstractClient do
200
197
  'Name' => 'Foobar')
201
198
  end
202
199
 
203
- it { should be_true }
200
+ it { should be true }
204
201
  end
205
202
  end
206
203
 
@@ -257,14 +254,14 @@ shared_examples_for Restforce::AbstractClient do
257
254
  context 'with success' do
258
255
  requests 'sobjects/Account/001D000000INjVe', method: :delete
259
256
 
260
- it { should be_true }
257
+ it { should be true }
261
258
  end
262
259
 
263
260
  context 'with a space in the id' do
264
261
  subject(:destroy!) { client.destroy!('Account', '001D000000 INjVe') }
265
262
  requests 'sobjects/Account/001D000000%20INjVe', method: :delete
266
263
 
267
- it { should be_true }
264
+ it { should be true }
268
265
  end
269
266
  end
270
267
 
@@ -277,13 +274,13 @@ shared_examples_for Restforce::AbstractClient do
277
274
  method: :delete,
278
275
  status: 404
279
276
 
280
- it { should be_false }
277
+ it { should be false }
281
278
  end
282
279
 
283
280
  context 'with success' do
284
281
  requests 'sobjects/Account/001D000000INjVe', method: :delete
285
282
 
286
- it { should be_true }
283
+ it { should be true }
287
284
  end
288
285
  end
289
286
 
@@ -368,8 +365,8 @@ shared_examples_for Restforce::AbstractClient do
368
365
  before do
369
366
  @request = stub_login_request(
370
367
  with_body: "grant_type=password&client_id=client_id" \
371
- "&client_secret=client_secret&username=foo" \
372
- "&password=barsecurity_token"
368
+ "&client_secret=client_secret&username=foo" \
369
+ "&password=barsecurity_token"
373
370
  ).to_return(status: 200, body: fixture(:auth_success_response))
374
371
  end
375
372
 
@@ -420,8 +417,8 @@ shared_examples_for Restforce::AbstractClient do
420
417
 
421
418
  @query_request = stub_login_request(
422
419
  with_body: "grant_type=password&client_id=client_id" \
423
- "&client_secret=client_secret&username=foo&" \
424
- "password=barsecurity_token"
420
+ "&client_secret=client_secret&username=foo&" \
421
+ "password=barsecurity_token"
425
422
  ).to_return(status: 200, body: fixture(:auth_success_response))
426
423
  end
427
424
 
@@ -445,7 +442,7 @@ shared_examples_for Restforce::AbstractClient do
445
442
 
446
443
  @login = stub_login_request(
447
444
  with_body: "grant_type=password&client_id=client_id&client_secret=" \
448
- "client_secret&username=foo&password=barsecurity_token"
445
+ "client_secret&username=foo&password=barsecurity_token"
449
446
  ).to_return(status: 200, body: fixture(:auth_success_response))
450
447
  end
451
448