restforce 1.5.2 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of restforce might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +29 -26
- data/lib/restforce.rb +6 -6
- data/lib/restforce/collection.rb +4 -0
- data/lib/restforce/concerns/api.rb +8 -6
- data/lib/restforce/config.rb +1 -0
- data/lib/restforce/version.rb +1 -1
- data/spec/unit/collection_spec.rb +2 -0
- data/spec/unit/concerns/api_spec.rb +2 -2
- data/spec/unit/config_spec.rb +10 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cea59c76c61a80f9b37c19dd5fcf0dc65724c706
|
4
|
+
data.tar.gz: 803df3bf79c4f7852dd1b1f604ec394981675ac6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc604478ae597a50c0f7ca90236df153a3065f3adca8527012f28e2904e71e0ccda68adedb372e88f183598d99054776cc4e7d5ba5823af200d77bb1fbf3526b
|
7
|
+
data.tar.gz: 5b4fb8dff7ea15b51cb6a6e64d7e3d60985eaa46e2fdf7054725c1c3790faaacbdec056757083a47461462a3b0d6362811725dd019e767932d187c70728fc4d1
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 1.5.3 (Jun 26, 2015)
|
2
|
+
|
3
|
+
* Fixed a bug with `update!` and `upsert!` mutating provided attributes (@timrogers)
|
4
|
+
* Added note about thread safety to `README.md` (@epbarger)
|
5
|
+
* Improved documentation for `select` in `README.md` (@theSteveMitchell)
|
6
|
+
* Tweaked and improved consistency of `README.md` (@timrogers)
|
7
|
+
* Pass through blocks given to `Restforce.new` (@jxa)
|
8
|
+
* Add `#page_size` to `Restforce::Collection` (@theSteveMitchell)
|
9
|
+
|
1
10
|
## 1.5.2 (Apr 29, 2015)
|
2
11
|
|
3
12
|
* Better autopagination performance #141 @th7
|
data/README.md
CHANGED
@@ -37,7 +37,7 @@ Or install it yourself as:
|
|
37
37
|
|
38
38
|
## Usage
|
39
39
|
|
40
|
-
Restforce is designed with flexibility and ease of use in mind. By default, all
|
40
|
+
Restforce is designed with flexibility and ease of use in mind. By default, all API calls will
|
41
41
|
return [Hashie::Mash](https://github.com/intridea/hashie/tree/v1.2.0) objects,
|
42
42
|
so you can do things like `client.query('select Id, (select Name from Children__r) from Account').Children__r.first.Name`.
|
43
43
|
|
@@ -52,6 +52,8 @@ If you're using the gem to interact with a single org (maybe you're building som
|
|
52
52
|
salesforce integration internally?) then you should use the username/password
|
53
53
|
authentication method.
|
54
54
|
|
55
|
+
It is also important to note that the client object should not be reused across different threads, otherwise you may encounter thread-safety issues.
|
56
|
+
|
55
57
|
#### OAuth token authentication
|
56
58
|
|
57
59
|
```ruby
|
@@ -60,7 +62,7 @@ client = Restforce.new :oauth_token => 'oauth token',
|
|
60
62
|
```
|
61
63
|
|
62
64
|
Although the above will work, you'll probably want to take advantage of the
|
63
|
-
(re)authentication middleware by specifying a
|
65
|
+
(re)authentication middleware by specifying a `refresh_token`, `client_id` and `client_secret`:
|
64
66
|
|
65
67
|
```ruby
|
66
68
|
client = Restforce.new :oauth_token => 'oauth token',
|
@@ -82,7 +84,7 @@ client = Restforce.new :username => 'foo',
|
|
82
84
|
:client_secret => 'client_secret'
|
83
85
|
```
|
84
86
|
|
85
|
-
You can also set the username, password, security token, client
|
87
|
+
You can also set the username, password, security token, client ID and client
|
86
88
|
secret in environment variables:
|
87
89
|
|
88
90
|
```bash
|
@@ -96,9 +98,10 @@ export SALESFORCE_CLIENT_SECRET="client secret"
|
|
96
98
|
```ruby
|
97
99
|
client = Restforce.new
|
98
100
|
```
|
101
|
+
|
99
102
|
### Proxy Support
|
100
103
|
|
101
|
-
You can specify a
|
104
|
+
You can specify a HTTP proxy using the `proxy_uri` option, as follows, or by setting the `PROXY_URI` environment variable:
|
102
105
|
|
103
106
|
```ruby
|
104
107
|
client = Restforce.new :username => 'foo',
|
@@ -108,7 +111,8 @@ client = Restforce.new :username => 'foo',
|
|
108
111
|
:client_secret => 'client_secret',
|
109
112
|
:proxy_uri => 'http://proxy.example.com:123'
|
110
113
|
```
|
111
|
-
|
114
|
+
|
115
|
+
You may specify a username and password for the proxy with a URL along the lines of 'http://user@password:proxy.example.com:123'.
|
112
116
|
|
113
117
|
#### Sandbox Orgs
|
114
118
|
|
@@ -118,11 +122,11 @@ You can connect to sandbox orgs by specifying a host. The default host is
|
|
118
122
|
```ruby
|
119
123
|
client = Restforce.new :host => 'test.salesforce.com'
|
120
124
|
```
|
121
|
-
The host can also be set with the environment variable SALESFORCE_HOST
|
125
|
+
The host can also be set with the environment variable `SALESFORCE_HOST`.
|
122
126
|
|
123
127
|
#### Global configuration
|
124
128
|
|
125
|
-
You can set any of the options passed into Restforce.new globally:
|
129
|
+
You can set any of the options passed into `Restforce.new` globally:
|
126
130
|
|
127
131
|
```ruby
|
128
132
|
Restforce.configure do |config|
|
@@ -133,8 +137,8 @@ end
|
|
133
137
|
|
134
138
|
### Bang! methods
|
135
139
|
|
136
|
-
All the CRUD methods (create
|
137
|
-
a ! at the end (create
|
140
|
+
All the CRUD methods (`create`, `update`, `upsert`, `destroy`) have equivalent methods with
|
141
|
+
a ! at the end (`create!`, `update!`, `upsert!`, `destroy!`), which can be used if you need
|
138
142
|
to do some custom error handling. The bang methods will raise exceptions, while the
|
139
143
|
non-bang methods will return false in the event that an exception is raised. This
|
140
144
|
works similarly to ActiveRecord.
|
@@ -176,14 +180,12 @@ client.find('Account', '1234', 'Some_External_Id_Field__c')
|
|
176
180
|
|
177
181
|
### select
|
178
182
|
|
179
|
-
|
180
|
-
client.select('Account', '001D000000INjVe', ["Id"])
|
181
|
-
# => {"attributes" : {"type" : "Account","url" : "/services/data/v20.0/sobjects/Account/001D000000INjVe"},
|
182
|
-
# "Id" : "001D000000INjVe"}
|
183
|
+
`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.
|
183
184
|
|
185
|
+
```ruby
|
186
|
+
# Select the `Id` column from a record with `Some_External_Id_Field__c` set to '001D000000INjVe'
|
184
187
|
client.select('Account', '001D000000INjVe', ["Id"], 'Some_External_Id_Field__c')
|
185
|
-
# => {"attributes" : {"type" : "Account","url" : "/services/data/v20.0/sobjects/Account/Some_External_Id_Field__c/001D000000INjVe"},
|
186
|
-
# "Id" : "003F000000BGIn3"}
|
188
|
+
# => {"attributes" : {"type" : "Account","url" : "/services/data/v20.0/sobjects/Account/Some_External_Id_Field__c/001D000000INjVe"}, "Id" : "003F000000BGIn3"}
|
187
189
|
```
|
188
190
|
|
189
191
|
### search
|
@@ -193,7 +195,7 @@ client.select('Account', '001D000000INjVe', ["Id"], 'Some_External_Id_Field__c')
|
|
193
195
|
client.search('FIND {bar}')
|
194
196
|
# => #<Restforce::Collection >
|
195
197
|
|
196
|
-
# Find accounts
|
198
|
+
# Find accounts matching the term 'genepoint' and return the `Name` field
|
197
199
|
client.search('FIND {genepoint} RETURNING Account (Name)').map(&:Name)
|
198
200
|
# => ['GenePoint']
|
199
201
|
```
|
@@ -209,7 +211,7 @@ client.create('Account', Name: 'Foobar Inc.')
|
|
209
211
|
### update
|
210
212
|
|
211
213
|
```ruby
|
212
|
-
# Update the Account with Id '0016000000MRatd'
|
214
|
+
# Update the Account with `Id` '0016000000MRatd'
|
213
215
|
client.update('Account', Id: '0016000000MRatd', Name: 'Whizbang Corp')
|
214
216
|
# => true
|
215
217
|
```
|
@@ -217,14 +219,14 @@ client.update('Account', Id: '0016000000MRatd', Name: 'Whizbang Corp')
|
|
217
219
|
### upsert
|
218
220
|
|
219
221
|
```ruby
|
220
|
-
# Update the record with external ID
|
222
|
+
# Update the record with external `External__c` external ID set to '12'
|
221
223
|
client.upsert('Account', 'External__c', External__c: 12, Name: 'Foobar')
|
222
224
|
```
|
223
225
|
|
224
226
|
### destroy
|
225
227
|
|
226
228
|
```ruby
|
227
|
-
# Delete the Account with Id '0016000000MRatd'
|
229
|
+
# Delete the Account with `Id` '0016000000MRatd'
|
228
230
|
client.destroy('Account', '0016000000MRatd')
|
229
231
|
# => true
|
230
232
|
```
|
@@ -232,11 +234,11 @@ client.destroy('Account', '0016000000MRatd')
|
|
232
234
|
### describe
|
233
235
|
|
234
236
|
```ruby
|
235
|
-
#
|
237
|
+
# Get the global describe for all sobjects
|
236
238
|
client.describe
|
237
239
|
# => { ... }
|
238
240
|
|
239
|
-
#
|
241
|
+
# Get the describe for the Account object
|
240
242
|
client.describe('Account')
|
241
243
|
# => { ... }
|
242
244
|
```
|
@@ -244,11 +246,11 @@ client.describe('Account')
|
|
244
246
|
### describe_layouts
|
245
247
|
|
246
248
|
```ruby
|
247
|
-
#
|
249
|
+
# Get layouts for an sobject type
|
248
250
|
client.describe_layout('Account')
|
249
251
|
# => { ... }
|
250
252
|
|
251
|
-
#
|
253
|
+
# Get the details for a specific layout by its ID
|
252
254
|
client.describe_layouts('Account', '012E0000000RHEp')
|
253
255
|
# => { ... }
|
254
256
|
```
|
@@ -257,12 +259,13 @@ client.describe_layouts('Account', '012E0000000RHEp')
|
|
257
259
|
|
258
260
|
|
259
261
|
```ruby
|
262
|
+
# Fetch picklist value for Account's `Type` field
|
260
263
|
client.picklist_values('Account', 'Type')
|
261
264
|
# => [#<Restforce::Mash label="Prospect" value="Prospect">]
|
262
265
|
|
263
266
|
# Given a custom object named Automobile__c with picklist fields
|
264
|
-
# Model__c and Make__c
|
265
|
-
# Make__c
|
267
|
+
# `Model__c` and `Make__c`, where options for `Model__c` depends on the value of
|
268
|
+
# `Make__c`.
|
266
269
|
client.picklist_values('Automobile__c', 'Model__c', :valid_for => 'Honda')
|
267
270
|
# => [#<Restforce::Mash label="Civic" value="Civic">, ... ]
|
268
271
|
```
|
@@ -270,7 +273,7 @@ client.picklist_values('Automobile__c', 'Model__c', :valid_for => 'Honda')
|
|
270
273
|
### user_info
|
271
274
|
|
272
275
|
```ruby
|
273
|
-
#
|
276
|
+
# Get info about the logged-in user
|
274
277
|
client.user_info
|
275
278
|
# => #<Restforce::Mash active=true display_name="Chatty Sassy" email="user@example.com" ... >
|
276
279
|
```
|
data/lib/restforce.rb
CHANGED
@@ -44,16 +44,16 @@ module Restforce
|
|
44
44
|
# Alias for Restforce::Data::Client.new
|
45
45
|
#
|
46
46
|
# Shamelessly pulled from https://github.com/pengwynn/octokit/blob/master/lib/octokit.rb
|
47
|
-
def new(*args)
|
48
|
-
data(*args)
|
47
|
+
def new(*args, &block)
|
48
|
+
data(*args, &block)
|
49
49
|
end
|
50
50
|
|
51
|
-
def data(*args)
|
52
|
-
Restforce::Data::Client.new(*args)
|
51
|
+
def data(*args, &block)
|
52
|
+
Restforce::Data::Client.new(*args, &block)
|
53
53
|
end
|
54
54
|
|
55
|
-
def tooling(*args)
|
56
|
-
Restforce::Tooling::Client.new(*args)
|
55
|
+
def tooling(*args, &block)
|
56
|
+
Restforce::Tooling::Client.new(*args, &block)
|
57
57
|
end
|
58
58
|
|
59
59
|
# Helper for decoding signed requests.
|
data/lib/restforce/collection.rb
CHANGED
@@ -220,9 +220,10 @@ module Restforce
|
|
220
220
|
# Returns true if the sobject was successfully updated.
|
221
221
|
# Raises an exception if an error is returned from Salesforce.
|
222
222
|
def update!(sobject, attrs)
|
223
|
-
id = attrs.
|
223
|
+
id = attrs.fetch(attrs.keys.find { |k, v| k.to_s.downcase == 'id' }, nil)
|
224
224
|
raise ArgumentError, 'Id field missing from attrs.' unless id
|
225
|
-
|
225
|
+
attrs_without_id = attrs.reject { |k, v| k.to_s.downcase == "id" }
|
226
|
+
api_patch "sobjects/#{sobject}/#{id}", attrs_without_id
|
226
227
|
true
|
227
228
|
end
|
228
229
|
|
@@ -261,8 +262,9 @@ module Restforce
|
|
261
262
|
# Returns the Id of the newly created record if the record was created.
|
262
263
|
# Raises an exception if an error is returned from Salesforce.
|
263
264
|
def upsert!(sobject, field, attrs)
|
264
|
-
external_id = attrs.
|
265
|
-
|
265
|
+
external_id = attrs.fetch(attrs.keys.find { |k, v| k.to_s.downcase == field.to_s.downcase }, nil)
|
266
|
+
attrs_without_field = attrs.reject { |k, v| k.to_s.downcase == field.to_s.downcase }
|
267
|
+
response = api_patch "sobjects/#{sobject}/#{field.to_s}/#{external_id}", attrs_without_field
|
266
268
|
(response.body && response.body['id']) ? response.body['id'] : true
|
267
269
|
end
|
268
270
|
|
@@ -319,13 +321,13 @@ module Restforce
|
|
319
321
|
# id - The id of the record. If field is specified, id should be the id
|
320
322
|
# of the external field.
|
321
323
|
# select - A String array denoting the fields to select. If nil or empty array
|
322
|
-
# is passed, all fields are selected.
|
324
|
+
# is passed, all fields are selected.
|
323
325
|
# field - External ID field to use (default: nil).
|
324
326
|
#
|
325
327
|
def select(sobject, id, select, field=nil)
|
326
328
|
path = field ? "sobjects/#{sobject}/#{field}/#{id}" : "sobjects/#{sobject}/#{id}"
|
327
329
|
path << "?fields=#{select.join(",")}" if select && select.any?
|
328
|
-
|
330
|
+
|
329
331
|
api_get(path).body
|
330
332
|
end
|
331
333
|
|
data/lib/restforce/config.rb
CHANGED
@@ -127,6 +127,7 @@ module Restforce
|
|
127
127
|
# Faraday adapter to use. Defaults to Faraday.default_adapter.
|
128
128
|
option :adapter, :default => lambda { Faraday.default_adapter }
|
129
129
|
|
130
|
+
# TODO: Rename this to `SALESFORCE_PROXY_URI` in next major version
|
130
131
|
option :proxy_uri, :default => lambda { ENV['PROXY_URI'] }
|
131
132
|
|
132
133
|
# A Proc that is called with the response body after a successful authentication.
|
data/lib/restforce/version.rb
CHANGED
@@ -13,6 +13,7 @@ describe Restforce::Collection do
|
|
13
13
|
its(:size) { should eq 1 }
|
14
14
|
its(:has_next_page?) { should be_false }
|
15
15
|
it { should have_client client }
|
16
|
+
its(:page_size) { should eq 1 }
|
16
17
|
|
17
18
|
describe 'each record' do
|
18
19
|
it { should be_all { |record| expect(record).to be_a Restforce::SObject } }
|
@@ -34,6 +35,7 @@ describe Restforce::Collection do
|
|
34
35
|
its(:first) { should be_a Restforce::SObject }
|
35
36
|
its(:current_page) { should be_a Array }
|
36
37
|
its(:current_page) { should have(1).element }
|
38
|
+
its(:page_size) { should eq 1 }
|
37
39
|
end
|
38
40
|
|
39
41
|
context 'when all of the values are being requested' do
|
@@ -177,11 +177,11 @@ describe Restforce::Concerns::API do
|
|
177
177
|
subject(:result) { client.update!(sobject, attrs) }
|
178
178
|
|
179
179
|
context 'when the id field is present' do
|
180
|
-
let(:attrs) { { :id => '1234' } }
|
180
|
+
let(:attrs) { { :id => '1234', :StageName => "Call Scheduled" } }
|
181
181
|
|
182
182
|
it 'sends an HTTP PATCH, and returns true' do
|
183
183
|
client.should_receive(:api_patch).
|
184
|
-
with('sobjects/Whizbang/1234',
|
184
|
+
with('sobjects/Whizbang/1234', { :StageName => "Call Scheduled" })
|
185
185
|
expect(result).to be_true
|
186
186
|
end
|
187
187
|
end
|
data/spec/unit/config_spec.rb
CHANGED
@@ -96,4 +96,14 @@ describe Restforce do
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
end
|
99
|
+
|
100
|
+
describe '.new' do
|
101
|
+
it 'calls its block' do
|
102
|
+
checker = double(:block_checker)
|
103
|
+
expect(checker).to receive(:check!).once
|
104
|
+
Restforce.new do |builder|
|
105
|
+
checker.check!
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
99
109
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restforce
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric J. Holmes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -272,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
272
272
|
version: '0'
|
273
273
|
requirements: []
|
274
274
|
rubyforge_project:
|
275
|
-
rubygems_version: 2.
|
275
|
+
rubygems_version: 2.4.7
|
276
276
|
signing_key:
|
277
277
|
specification_version: 4
|
278
278
|
summary: A lightweight ruby client for the Salesforce REST api.
|