restforce 3.0.1 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +9 -9
  3. data/.github/ISSUE_TEMPLATE/unhandled-salesforce-error.md +17 -0
  4. data/.github/dependabot.yml +19 -0
  5. data/.rubocop.yml +13 -14
  6. data/.rubocop_todo.yml +128 -81
  7. data/CHANGELOG.md +107 -1
  8. data/CONTRIBUTING.md +21 -1
  9. data/Dockerfile +31 -0
  10. data/Gemfile +10 -6
  11. data/README.md +168 -31
  12. data/UPGRADING.md +38 -0
  13. data/docker-compose.yml +7 -0
  14. data/lib/restforce/abstract_client.rb +1 -0
  15. data/lib/restforce/attachment.rb +1 -0
  16. data/lib/restforce/collection.rb +7 -2
  17. data/lib/restforce/concerns/api.rb +10 -7
  18. data/lib/restforce/concerns/authentication.rb +10 -0
  19. data/lib/restforce/concerns/base.rb +4 -2
  20. data/lib/restforce/concerns/batch_api.rb +87 -0
  21. data/lib/restforce/concerns/caching.rb +7 -0
  22. data/lib/restforce/concerns/canvas.rb +1 -0
  23. data/lib/restforce/concerns/connection.rb +3 -3
  24. data/lib/restforce/concerns/picklists.rb +4 -3
  25. data/lib/restforce/concerns/streaming.rb +73 -3
  26. data/lib/restforce/config.rb +8 -1
  27. data/lib/restforce/document.rb +1 -0
  28. data/lib/restforce/error_code.rb +638 -0
  29. data/lib/restforce/file_part.rb +24 -0
  30. data/lib/restforce/mash.rb +8 -3
  31. data/lib/restforce/middleware/authentication/jwt_bearer.rb +38 -0
  32. data/lib/restforce/middleware/authentication.rb +7 -3
  33. data/lib/restforce/middleware/caching.rb +1 -1
  34. data/lib/restforce/middleware/instance_url.rb +1 -1
  35. data/lib/restforce/middleware/logger.rb +8 -7
  36. data/lib/restforce/middleware/multipart.rb +1 -0
  37. data/lib/restforce/middleware/raise_error.rb +24 -9
  38. data/lib/restforce/middleware.rb +2 -0
  39. data/lib/restforce/signed_request.rb +1 -0
  40. data/lib/restforce/sobject.rb +1 -0
  41. data/lib/restforce/tooling/client.rb +3 -3
  42. data/lib/restforce/version.rb +1 -1
  43. data/lib/restforce.rb +21 -3
  44. data/restforce.gemspec +11 -20
  45. data/spec/fixtures/test_private.key +27 -0
  46. data/spec/integration/abstract_client_spec.rb +83 -33
  47. data/spec/integration/data/client_spec.rb +6 -2
  48. data/spec/spec_helper.rb +24 -1
  49. data/spec/support/client_integration.rb +7 -7
  50. data/spec/support/concerns.rb +1 -1
  51. data/spec/support/fixture_helpers.rb +3 -5
  52. data/spec/support/middleware.rb +1 -2
  53. data/spec/unit/collection_spec.rb +20 -2
  54. data/spec/unit/concerns/api_spec.rb +12 -12
  55. data/spec/unit/concerns/authentication_spec.rb +39 -4
  56. data/spec/unit/concerns/batch_api_spec.rb +107 -0
  57. data/spec/unit/concerns/caching_spec.rb +26 -0
  58. data/spec/unit/concerns/connection_spec.rb +2 -2
  59. data/spec/unit/concerns/streaming_spec.rb +144 -4
  60. data/spec/unit/config_spec.rb +1 -1
  61. data/spec/unit/error_code_spec.rb +61 -0
  62. data/spec/unit/mash_spec.rb +5 -0
  63. data/spec/unit/middleware/authentication/jwt_bearer_spec.rb +62 -0
  64. data/spec/unit/middleware/authentication/password_spec.rb +2 -2
  65. data/spec/unit/middleware/authentication/token_spec.rb +2 -2
  66. data/spec/unit/middleware/authentication_spec.rb +31 -4
  67. data/spec/unit/middleware/gzip_spec.rb +2 -2
  68. data/spec/unit/middleware/raise_error_spec.rb +57 -17
  69. data/spec/unit/signed_request_spec.rb +1 -1
  70. data/spec/unit/sobject_spec.rb +2 -5
  71. metadata +39 -108
  72. data/lib/restforce/upload_io.rb +0 -9
@@ -34,7 +34,8 @@ module Restforce
34
34
  @field = field
35
35
  @valid_for = options.delete(:valid_for)
36
36
  raise "#{field} is not a dependent picklist" if @valid_for && !dependent?
37
- replace(picklist_values)
37
+
38
+ super(picklist_values)
38
39
  end
39
40
 
40
41
  private
@@ -82,9 +83,9 @@ module Restforce
82
83
  # See http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_des
83
84
  # cribesobjects_describesobjectresult.htm
84
85
  def valid?(picklist_entry)
85
- valid_for = picklist_entry['validFor'].ljust(16, 'A').unpack('m').first.
86
+ valid_for = picklist_entry['validFor'].ljust(16, 'A').unpack1('m').
86
87
  unpack('C*')
87
- (valid_for[index >> 3] & (0x80 >> index % 8)).positive?
88
+ (valid_for[index >> 3] & (0x80 >> (index % 8))).positive?
88
89
  end
89
90
  end
90
91
  end
@@ -5,12 +5,28 @@ module Restforce
5
5
  module Streaming
6
6
  # Public: Subscribe to a PushTopic
7
7
  #
8
- # channels - The name of the PushTopic channel(s) to subscribe to.
8
+ # topics - The name of the PushTopic channel(s) to subscribe to.
9
9
  # block - A block to run when a new message is received.
10
10
  #
11
11
  # Returns a Faye::Subscription
12
- def subscribe(channels, &block)
13
- faye.subscribe Array(channels).map { |channel| "/topic/#{channel}" }, &block
12
+ def legacy_subscribe(topics, options = {}, &block)
13
+ topics = Array(topics).map { |channel| "/topic/#{channel}" }
14
+ subscription(topics, options, &block)
15
+ end
16
+ alias subscribe legacy_subscribe
17
+
18
+ # Public: Subscribe to one or more Streaming API channels
19
+ #
20
+ # channels - The name of the Streaming API (cometD) channel(s) to subscribe to.
21
+ # block - A block to run when a new message is received.
22
+ #
23
+ # Returns a Faye::Subscription
24
+ def subscription(channels, options = {}, &block)
25
+ one_or_more_channels = Array(channels)
26
+ one_or_more_channels.each do |channel|
27
+ replay_handlers[channel] = options[:replay]
28
+ end
29
+ faye.subscribe(one_or_more_channels, &block)
14
30
  end
15
31
 
16
32
  # Public: Faye client to use for subscribing to PushTopics
@@ -32,6 +48,60 @@ module Restforce
32
48
  client.bind 'transport:up' do
33
49
  Restforce.log "[COMETD UP]"
34
50
  end
51
+
52
+ client.add_extension ReplayExtension.new(replay_handlers)
53
+ end
54
+ end
55
+
56
+ def replay_handlers
57
+ @_replay_handlers ||= {}
58
+ end
59
+
60
+ class ReplayExtension
61
+ def initialize(replay_handlers)
62
+ @replay_handlers = replay_handlers
63
+ end
64
+
65
+ def incoming(message, callback)
66
+ callback.call(message).tap do
67
+ channel = message.fetch('channel')
68
+ replay_id = message.fetch('data', {}).fetch('event', {})['replayId']
69
+
70
+ handler = @replay_handlers[channel]
71
+ if !replay_id.nil? && !handler.nil? && handler.respond_to?(:[]=)
72
+ # remember the last replay_id for this channel
73
+ handler[channel] = replay_id
74
+ end
75
+ end
76
+ end
77
+
78
+ def outgoing(message, callback)
79
+ # Leave non-subscribe messages alone
80
+ return callback.call(message) unless message['channel'] == '/meta/subscribe'
81
+
82
+ channel = message['subscription']
83
+
84
+ # Set the replay value for the channel
85
+ message['ext'] ||= {}
86
+ message['ext']['replay'] = {
87
+ channel => replay_id(channel)
88
+ }
89
+
90
+ # Carry on and send the message to the server
91
+ callback.call message
92
+ end
93
+
94
+ private
95
+
96
+ def replay_id(channel)
97
+ handler = @replay_handlers[channel]
98
+ if handler.respond_to?(:[]) && !handler.is_a?(Integer)
99
+ # Ask for the latest replayId for this channel
100
+ handler[channel]
101
+ else
102
+ # Just pass it along
103
+ handler
104
+ end
35
105
  end
36
106
  end
37
107
  end
@@ -34,6 +34,7 @@ module Restforce
34
34
 
35
35
  def log(message)
36
36
  return unless Restforce.log?
37
+
37
38
  configuration.logger.send(configuration.log_level, message)
38
39
  end
39
40
  end
@@ -107,6 +108,9 @@ module Restforce
107
108
  # The OAuth client secret
108
109
  option :client_secret, default: lambda { ENV['SALESFORCE_CLIENT_SECRET'] }
109
110
 
111
+ # The private key for JWT authentication
112
+ option :jwt_key
113
+
110
114
  # Set this to true if you're authenticating with a Sandbox instance.
111
115
  # Defaults to false.
112
116
  option :host, default: lambda { ENV['SALESFORCE_HOST'] || 'login.salesforce.com' }
@@ -147,11 +151,14 @@ module Restforce
147
151
  option :request_headers
148
152
 
149
153
  # Set a logger for when Restforce.log is set to true, defaulting to STDOUT
150
- option :logger, default: ::Logger.new(STDOUT)
154
+ option :logger, default: ::Logger.new($stdout)
151
155
 
152
156
  # Set a log level for logging when Restforce.log is set to true, defaulting to :debug
153
157
  option :log_level, default: :debug
154
158
 
159
+ # Set use_cache to false to opt in to caching with client.with_caching
160
+ option :use_cache, default: true
161
+
155
162
  def options
156
163
  self.class.options
157
164
  end
@@ -17,6 +17,7 @@ module Restforce
17
17
 
18
18
  def ensure_body
19
19
  return true if self.Body?
20
+
20
21
  raise 'You need to query the Body for the record first.'
21
22
  end
22
23
  end