salesforce_bulk_api 1.1.0 → 1.3.0
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.
- checksums.yaml +4 -4
- data/.env.sample +7 -0
- data/.github/workflows/ci.yml +36 -0
- data/.gitignore +1 -0
- data/.rspec +1 -1
- data/.rubocop.yml +1927 -0
- data/CHANGELOG.md +0 -0
- data/LICENCE +1 -1
- data/README.md +426 -71
- data/Rakefile +3 -3
- data/lib/salesforce_bulk_api/concerns/throttling.rb +1 -3
- data/lib/salesforce_bulk_api/connection.rb +12 -14
- data/lib/salesforce_bulk_api/job.rb +83 -85
- data/lib/salesforce_bulk_api/version.rb +1 -1
- data/lib/salesforce_bulk_api.rb +21 -22
- data/salesforce_bulk_api.gemspec +20 -18
- data/spec/salesforce_bulk_api/salesforce_bulk_api_spec.rb +100 -143
- data/spec/spec_helper.rb +7 -4
- metadata +81 -12
@@ -1,193 +1,150 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "yaml"
|
3
|
+
require "restforce"
|
4
4
|
|
5
5
|
describe SalesforceBulkApi do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@sf_client.authenticate!
|
18
|
-
|
19
|
-
@account_id = auth_hash['salesforce']['test_account_id']
|
20
|
-
|
21
|
-
@api = SalesforceBulkApi::Api.new(@sf_client)
|
22
|
-
end
|
23
|
-
|
24
|
-
after :each do
|
25
|
-
|
6
|
+
let(:sf_client) do
|
7
|
+
client = Restforce.new(
|
8
|
+
username: ENV["SALESFORCE_USERNAME"],
|
9
|
+
password: ENV["SALESFORCE_PASSWORD"],
|
10
|
+
client_id: ENV["SALESFORCE_CLIENT_ID"],
|
11
|
+
client_secret: ENV["SALESFORCE_CLIENT_SECRET"],
|
12
|
+
host: ENV["SALESFORCE_HOST"],
|
13
|
+
security_token: ENV["SALESFORCE_SECURITY_TOKEN"]
|
14
|
+
)
|
15
|
+
client.authenticate!
|
16
|
+
client
|
26
17
|
end
|
27
18
|
|
28
|
-
|
19
|
+
let(:account_id) { ENV["SALESFORCE_TEST_ACCOUNT_ID"] }
|
20
|
+
let(:api) { SalesforceBulkApi::Api.new(sf_client) }
|
29
21
|
|
30
|
-
|
22
|
+
describe "upsert" do
|
23
|
+
context "when not passed get_result" do
|
31
24
|
it "doesn't return the batches array" do
|
32
|
-
res =
|
33
|
-
res[
|
25
|
+
res = api.upsert("Account", [{Id: account_id, Website: "www.test.com"}], "Id")
|
26
|
+
expect(res["batches"]).to be_nil
|
34
27
|
end
|
35
28
|
end
|
36
29
|
|
37
|
-
context
|
38
|
-
it
|
39
|
-
res =
|
40
|
-
res[
|
41
|
-
|
42
|
-
res['batches'][0]['response'][0]['id'][0].should start_with(@account_id)
|
43
|
-
res['batches'][0]['response'][0]['success'].should eq ['true']
|
44
|
-
res['batches'][0]['response'][0]['created'].should eq ['false']
|
30
|
+
context "when passed get_result = true" do
|
31
|
+
it "returns the batches array" do
|
32
|
+
res = api.upsert("Account", [{Id: account_id, Website: "www.test.com"}], "Id", true)
|
33
|
+
expect(res["batches"][0]["response"]).to be_a Array
|
45
34
|
|
35
|
+
expect(res["batches"][0]["response"][0]["id"][0]).to start_with(account_id)
|
36
|
+
expect(res["batches"][0]["response"][0]["success"]).to eq ["true"]
|
37
|
+
expect(res["batches"][0]["response"][0]["created"]).to eq ["false"]
|
46
38
|
end
|
47
39
|
end
|
48
40
|
|
49
|
-
context
|
50
|
-
it
|
51
|
-
|
52
|
-
res =
|
53
|
-
res[
|
54
|
-
res[
|
55
|
-
res =
|
56
|
-
res[
|
57
|
-
res[
|
58
|
-
res[
|
59
|
-
res =
|
60
|
-
res[
|
61
|
-
res[
|
41
|
+
context "when passed send_nulls = true" do
|
42
|
+
it "sets the nil and empty attributes to NULL" do
|
43
|
+
api.update("Account", [{Id: account_id, Website: "abc123", Phone: "5678"}], true)
|
44
|
+
res = api.query("Account", "SELECT Website, Phone From Account WHERE Id = '#{account_id}'")
|
45
|
+
expect(res["batches"][0]["response"][0]["Website"][0]).to eq "abc123"
|
46
|
+
expect(res["batches"][0]["response"][0]["Phone"][0]).to eq "5678"
|
47
|
+
res = api.upsert("Account", [{Id: account_id, Website: "", Phone: nil}], "Id", true, true)
|
48
|
+
expect(res["batches"][0]["response"][0]["id"][0]).to start_with(account_id)
|
49
|
+
expect(res["batches"][0]["response"][0]["success"]).to eq ["true"]
|
50
|
+
expect(res["batches"][0]["response"][0]["created"]).to eq ["false"]
|
51
|
+
res = api.query("Account", "SELECT Website, Phone From Account WHERE Id = '#{account_id}'")
|
52
|
+
expect(res["batches"][0]["response"][0]["Website"][0]).to eq({"xsi:nil" => "true"})
|
53
|
+
expect(res["batches"][0]["response"][0]["Phone"][0]).to eq({"xsi:nil" => "true"})
|
62
54
|
end
|
63
55
|
end
|
64
56
|
|
65
|
-
context
|
66
|
-
it
|
67
|
-
|
68
|
-
res =
|
69
|
-
res[
|
70
|
-
res[
|
71
|
-
res =
|
72
|
-
res[
|
73
|
-
res[
|
74
|
-
res[
|
75
|
-
res =
|
76
|
-
res[
|
77
|
-
res[
|
57
|
+
context "when passed send_nulls = true and an array of fields not to null" do
|
58
|
+
it "sets the nil and empty attributes to NULL, except for those included in the list of fields to ignore" do
|
59
|
+
api.update("Account", [{Id: account_id, Website: "abc123", Phone: "5678"}], true)
|
60
|
+
res = api.query("Account", "SELECT Website, Phone From Account WHERE Id = '#{account_id}'")
|
61
|
+
expect(res["batches"][0]["response"][0]["Website"][0]).to eq "abc123"
|
62
|
+
expect(res["batches"][0]["response"][0]["Phone"][0]).to eq "5678"
|
63
|
+
res = api.upsert("Account", [{Id: account_id, Website: "", Phone: nil}], "Id", true, true, [:Website, :Phone])
|
64
|
+
expect(res["batches"][0]["response"][0]["id"][0]).to start_with(account_id)
|
65
|
+
expect(res["batches"][0]["response"][0]["success"]).to eq ["true"]
|
66
|
+
expect(res["batches"][0]["response"][0]["created"]).to eq ["false"]
|
67
|
+
res = api.query("Account", "SELECT Website, Phone From Account WHERE Id = '#{account_id}'")
|
68
|
+
expect(res["batches"][0]["response"][0]["Website"][0]).to eq("abc123")
|
69
|
+
expect(res["batches"][0]["response"][0]["Phone"][0]).to eq("5678")
|
78
70
|
end
|
79
71
|
end
|
80
|
-
|
81
72
|
end
|
82
73
|
|
83
|
-
describe
|
84
|
-
context
|
85
|
-
context
|
74
|
+
describe "update" do
|
75
|
+
context "when there is not an error" do
|
76
|
+
context "when not passed get_result" do
|
86
77
|
it "doesnt return the batches array" do
|
87
|
-
res =
|
88
|
-
res[
|
78
|
+
res = api.update("Account", [{Id: account_id, Website: "www.test.com"}])
|
79
|
+
expect(res["batches"]).to be_nil
|
89
80
|
end
|
90
81
|
end
|
91
82
|
|
92
|
-
context
|
93
|
-
it
|
94
|
-
res =
|
95
|
-
res[
|
96
|
-
res[
|
97
|
-
res[
|
98
|
-
res[
|
83
|
+
context "when passed get_result = true" do
|
84
|
+
it "returns the batches array" do
|
85
|
+
res = api.update("Account", [{Id: account_id, Website: "www.test.com"}], true)
|
86
|
+
expect(res["batches"][0]["response"]).to be_a Array
|
87
|
+
expect(res["batches"][0]["response"][0]["id"][0]).to start_with(account_id)
|
88
|
+
expect(res["batches"][0]["response"][0]["success"]).to eq ["true"]
|
89
|
+
expect(res["batches"][0]["response"][0]["created"]).to eq ["false"]
|
99
90
|
end
|
100
91
|
end
|
101
92
|
end
|
102
93
|
|
103
|
-
context
|
104
|
-
context
|
94
|
+
context "when there is an error" do
|
95
|
+
context "when not passed get_result" do
|
105
96
|
it "doesn't return the results array" do
|
106
|
-
res =
|
107
|
-
res[
|
97
|
+
res = api.update("Account", [{Id: account_id, Website: "www.test.com"}, {Id: "abc123", Website: "www.test.com"}])
|
98
|
+
expect(res["batches"]).to be_nil
|
108
99
|
end
|
109
100
|
end
|
110
101
|
|
111
|
-
context
|
112
|
-
it
|
113
|
-
res =
|
114
|
-
|
115
|
-
res[
|
116
|
-
res[
|
117
|
-
res[
|
118
|
-
res[
|
119
|
-
res[
|
120
|
-
res[
|
121
|
-
|
122
|
-
res[
|
123
|
-
res[
|
124
|
-
res[
|
125
|
-
res[
|
102
|
+
context "when passed get_result = true with batches" do
|
103
|
+
it "returns the results array" do
|
104
|
+
res = api.update("Account", [{Id: account_id, Website: "www.test.com"}, {Id: account_id, Website: "www.test.com"}, {Id: account_id, Website: "www.test.com"}, {Id: "abc123", Website: "www.test.com"}], true, false, [], 2)
|
105
|
+
|
106
|
+
expect(res["batches"][0]["response"][0]["id"][0]).to start_with(account_id)
|
107
|
+
expect(res["batches"][0]["response"][0]["success"]).to eq ["true"]
|
108
|
+
expect(res["batches"][0]["response"][0]["created"]).to eq ["false"]
|
109
|
+
expect(res["batches"][0]["response"][1]["id"][0]).to start_with(account_id)
|
110
|
+
expect(res["batches"][0]["response"][1]["success"]).to eq ["true"]
|
111
|
+
expect(res["batches"][0]["response"][1]["created"]).to eq ["false"]
|
112
|
+
|
113
|
+
expect(res["batches"][1]["response"][0]["id"][0]).to start_with(account_id)
|
114
|
+
expect(res["batches"][1]["response"][0]["success"]).to eq ["true"]
|
115
|
+
expect(res["batches"][1]["response"][0]["created"]).to eq ["false"]
|
116
|
+
expect(res["batches"][1]["response"][1]).to eq({"errors" => [{"fields" => ["Id"], "message" => ["Account ID: id value of incorrect type: abc123"], "statusCode" => ["MALFORMED_ID"]}], "success" => ["false"], "created" => ["false"]})
|
126
117
|
end
|
127
118
|
end
|
128
119
|
end
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
describe 'create' do
|
133
|
-
pending
|
134
120
|
end
|
135
121
|
|
136
|
-
describe
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
context 'when there are results' do
|
143
|
-
it 'returns the query results' do
|
144
|
-
res = @api.query('Account', "SELECT id, Name From Account WHERE Name LIKE 'Test%'")
|
145
|
-
res['batches'][0]['response'].length.should > 1
|
146
|
-
res['batches'][0]['response'][0]['Id'].should_not be_nil
|
122
|
+
describe "query" do
|
123
|
+
context "when there are results" do
|
124
|
+
it "returns the query results" do
|
125
|
+
res = api.query("Account", "SELECT id, Name From Account WHERE Name LIKE 'Test%'")
|
126
|
+
expect(res["batches"][0]["response"].length).to be > 1
|
127
|
+
expect(res["batches"][0]["response"][0]["Id"]).not_to be_nil
|
147
128
|
end
|
148
129
|
|
149
|
-
context
|
130
|
+
context "and there are multiple batches" do
|
150
131
|
# need dev to create > 10k records in dev organization
|
151
|
-
it
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
context 'when there are no results' do
|
156
|
-
it 'returns nil' do
|
157
|
-
res = @api.query('Account', "SELECT id From Account WHERE Name = 'ABC'")
|
158
|
-
res['batches'][0]['response'].should eq nil
|
132
|
+
it "returns the query results in a merged hash"
|
159
133
|
end
|
160
134
|
end
|
161
135
|
|
162
|
-
context
|
163
|
-
it
|
164
|
-
res =
|
165
|
-
res[
|
136
|
+
context "when there are no results" do
|
137
|
+
it "returns nil" do
|
138
|
+
res = api.query("Account", "SELECT id From Account WHERE Name = 'ABC'")
|
139
|
+
expect(res["batches"][0]["response"]).to be_nil
|
166
140
|
end
|
167
141
|
end
|
168
142
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
it 'increments operation count and http GET count' do
|
174
|
-
@api.counters[:http_get].should eq 0
|
175
|
-
@api.counters[:query].should eq 0
|
176
|
-
@api.query('Account', "SELECT Website, Phone From Account WHERE Id = '#{@account_id}'")
|
177
|
-
@api.counters[:http_get].should eq 1
|
178
|
-
@api.counters[:query].should eq 1
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
context 'when update operations are called' do
|
183
|
-
it 'increments operation count and http POST count' do
|
184
|
-
@api.counters[:http_post].should eq 0
|
185
|
-
@api.counters[:update].should eq 0
|
186
|
-
@api.update('Account', [{:Id => @account_id, :Website => 'abc123', :Phone => '5678'}], true)
|
187
|
-
@api.counters[:http_post].should eq 1
|
188
|
-
@api.counters[:update].should eq 1
|
143
|
+
context "when there is an error" do
|
144
|
+
it "returns nil" do
|
145
|
+
res = api.query("Account", "SELECT id From Account WHERE Name = ''ABC'")
|
146
|
+
expect(res["batches"][0]["response"]).to be_nil
|
189
147
|
end
|
190
148
|
end
|
191
149
|
end
|
192
|
-
|
193
150
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require "salesforce_bulk_api"
|
4
|
+
|
5
|
+
require "dotenv"
|
6
|
+
Dotenv.load
|
4
7
|
|
5
8
|
RSpec.configure do |c|
|
6
|
-
c.filter_run :
|
9
|
+
c.filter_run focus: true
|
7
10
|
c.run_all_when_everything_filtered = true
|
8
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: salesforce_bulk_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yatish Mehta
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: json
|
@@ -38,6 +37,34 @@ dependencies:
|
|
38
37
|
- - ">="
|
39
38
|
- !ruby/object:Gem::Version
|
40
39
|
version: '0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: csv
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: logger
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
41
68
|
- !ruby/object:Gem::Dependency
|
42
69
|
name: rspec
|
43
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +85,14 @@ dependencies:
|
|
58
85
|
requirements:
|
59
86
|
- - "~>"
|
60
87
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
88
|
+
version: 8.0.0
|
62
89
|
type: :development
|
63
90
|
prerelease: false
|
64
91
|
version_requirements: !ruby/object:Gem::Requirement
|
65
92
|
requirements:
|
66
93
|
- - "~>"
|
67
94
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
95
|
+
version: 8.0.0
|
69
96
|
- !ruby/object:Gem::Dependency
|
70
97
|
name: rake
|
71
98
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,15 +121,61 @@ dependencies:
|
|
94
121
|
- - ">="
|
95
122
|
- !ruby/object:Gem::Version
|
96
123
|
version: '0'
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: rubocop
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
type: :development
|
132
|
+
prerelease: false
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
- !ruby/object:Gem::Dependency
|
139
|
+
name: rubocop-rake
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
type: :development
|
146
|
+
prerelease: false
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
- !ruby/object:Gem::Dependency
|
153
|
+
name: dotenv
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
type: :development
|
160
|
+
prerelease: false
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
97
166
|
description: Salesforce Bulk API with governor limits taken care of
|
98
167
|
email:
|
99
|
-
-
|
168
|
+
- yatish27@users.noreply.github.com
|
100
169
|
executables: []
|
101
170
|
extensions: []
|
102
171
|
extra_rdoc_files: []
|
103
172
|
files:
|
173
|
+
- ".env.sample"
|
174
|
+
- ".github/workflows/ci.yml"
|
104
175
|
- ".gitignore"
|
105
176
|
- ".rspec"
|
177
|
+
- ".rubocop.yml"
|
178
|
+
- CHANGELOG.md
|
106
179
|
- Gemfile
|
107
180
|
- LICENCE
|
108
181
|
- README.md
|
@@ -119,7 +192,6 @@ files:
|
|
119
192
|
homepage: https://github.com/yatishmehta27/salesforce_bulk_api
|
120
193
|
licenses: []
|
121
194
|
metadata: {}
|
122
|
-
post_install_message:
|
123
195
|
rdoc_options: []
|
124
196
|
require_paths:
|
125
197
|
- lib
|
@@ -134,10 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
206
|
- !ruby/object:Gem::Version
|
135
207
|
version: '0'
|
136
208
|
requirements: []
|
137
|
-
rubygems_version: 3.
|
138
|
-
signing_key:
|
209
|
+
rubygems_version: 3.6.7
|
139
210
|
specification_version: 4
|
140
211
|
summary: It uses the bulk api of salesforce to communicate with Salesforce CRM
|
141
|
-
test_files:
|
142
|
-
- spec/salesforce_bulk_api/salesforce_bulk_api_spec.rb
|
143
|
-
- spec/spec_helper.rb
|
212
|
+
test_files: []
|