activeforce 1.8.0 → 1.9.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 +7 -7
- data/Gemfile.lock +8 -6
- data/lib/activeforce.rb +1 -0
- data/lib/activeforce/version.rb +2 -2
- data/lib/salesforce/bulk/operations.rb +8 -0
- data/lib/salesforce/bulk/upsert_job.rb +38 -0
- data/test/salesforce/bulk/upsert_job_test.rb +134 -0
- metadata +85 -62
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ee133e1f38fd2878fae6ad22990f625a434b2fdc
|
4
|
+
data.tar.gz: ec6a6096cbe30589dec37bd467b362a01012ccd1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b39056785f47e3dc32959d1fe8b989cfd26480c86ba3ebad486e65cf358c2c233abfbb9a08b5a2e055b8bed54cdacfece9fd6d21bf86677adad9897bf0f1901e
|
7
|
+
data.tar.gz: 3ed81dc8bc50798555fa1e43123e888f68617755bb86c42332b62be1fa72a3bd56d4fa036909d73369ce3e8c887aabe6fb3d26917858089c785e91c7a0d27588
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activeforce (1.
|
4
|
+
activeforce (1.9.0)
|
5
5
|
blockenspiel
|
6
6
|
fastercsv
|
7
7
|
rails (>= 3.0)
|
@@ -53,16 +53,18 @@ GEM
|
|
53
53
|
rack
|
54
54
|
i18n (0.6.5)
|
55
55
|
journey (1.0.4)
|
56
|
-
json (1.8.
|
56
|
+
json (1.8.1)
|
57
57
|
mail (2.5.4)
|
58
58
|
mime-types (~> 1.16)
|
59
59
|
treetop (~> 1.4.8)
|
60
60
|
metaclass (0.0.1)
|
61
|
-
mime-types (1.
|
61
|
+
mime-types (1.25)
|
62
|
+
mini_portile (0.5.1)
|
62
63
|
mocha (0.14.0)
|
63
64
|
metaclass (~> 0.0.1)
|
64
|
-
multi_json (1.
|
65
|
-
nokogiri (1.
|
65
|
+
multi_json (1.8.2)
|
66
|
+
nokogiri (1.6.0)
|
67
|
+
mini_portile (~> 0.5.0)
|
66
68
|
nori (1.1.3)
|
67
69
|
polyglot (0.3.3)
|
68
70
|
rack (1.4.5)
|
@@ -110,7 +112,7 @@ GEM
|
|
110
112
|
treetop (1.4.15)
|
111
113
|
polyglot
|
112
114
|
polyglot (>= 0.3.1)
|
113
|
-
tzinfo (0.3.
|
115
|
+
tzinfo (0.3.38)
|
114
116
|
wasabi (2.5.0)
|
115
117
|
httpi (~> 1.0)
|
116
118
|
nokogiri (>= 1.4.0)
|
data/lib/activeforce.rb
CHANGED
data/lib/activeforce/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Activeforce
|
2
|
-
VERSION = '1.
|
3
|
-
end
|
2
|
+
VERSION = '1.9.0'.freeze
|
3
|
+
end
|
@@ -19,6 +19,14 @@ module Salesforce
|
|
19
19
|
job.process!
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
def bulk_upsert(external_id, columns = [], &block)
|
24
|
+
UpsertJob.new(self, external_id, columns).tap do |job|
|
25
|
+
Blockenspiel.invoke(block, job)
|
26
|
+
job.process!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
end
|
23
31
|
end
|
24
32
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Salesforce
|
2
|
+
module Bulk
|
3
|
+
class UpsertJob < Job
|
4
|
+
|
5
|
+
attr_accessor :external_id_col
|
6
|
+
|
7
|
+
def initialize(object_type, external_id_col, columns = :all)
|
8
|
+
super(object_type, 'upsert', columns)
|
9
|
+
self.external_id_col = object_type.columns.find { |scol| scol.name == external_id_col.to_s }
|
10
|
+
raise UnrecognizedColumn.new("#{external_id_col} is not a valid column.") unless self.external_id_col
|
11
|
+
end
|
12
|
+
|
13
|
+
def csv_columns
|
14
|
+
if columns.blank? || columns == :all
|
15
|
+
([self.external_id_col] + object_type.columns.editable).uniq
|
16
|
+
else
|
17
|
+
cols = columns.map do |col|
|
18
|
+
sf_col = object_type.columns.find { |scol| scol.name == col.to_s }
|
19
|
+
raise UnrecognizedColumn.new("#{col} is not a valid column.") unless sf_col
|
20
|
+
sf_col
|
21
|
+
end
|
22
|
+
([self.external_id_col] + cols).uniq
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_job_xml
|
27
|
+
job_xml do |job_info|
|
28
|
+
job_info.operation self.operation
|
29
|
+
job_info.object self.object
|
30
|
+
job_info.externalIdFieldName self.external_id_col.original_name
|
31
|
+
job_info.contentType "CSV"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Salesforce::Bulk::UpsertJobTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
setup :setup_columns_for_bulk_table
|
6
|
+
setup :setup_columns_for_account
|
7
|
+
|
8
|
+
|
9
|
+
def test_initialize
|
10
|
+
job = Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id")
|
11
|
+
assert_equal Salesforce::Account, job.object_type
|
12
|
+
assert_equal 'upsert', job.operation
|
13
|
+
assert_equal 'Parallel', job.concurrency_mode
|
14
|
+
assert_equal 'Account', job.object
|
15
|
+
assert_equal 'id', job.external_id_col.name
|
16
|
+
assert_equal ["Id","City","Address","Name", "Number", "Type","State"].sort, job.send(:csv_header).sort
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_initialize__with_columns
|
20
|
+
job = Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id", [:name, :state])
|
21
|
+
assert_equal Salesforce::Account, job.object_type
|
22
|
+
assert_equal 'upsert', job.operation
|
23
|
+
assert_equal 'Parallel', job.concurrency_mode
|
24
|
+
assert_equal 'Account', job.object
|
25
|
+
assert_equal 'id', job.external_id_col.name
|
26
|
+
assert_equal 'Id,Name,State', job.send(:csv_header).join(',')
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_initialize__with_all
|
30
|
+
job = Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id", :all)
|
31
|
+
assert_equal Salesforce::Account, job.object_type
|
32
|
+
assert_equal 'upsert', job.operation
|
33
|
+
assert_equal 'Parallel', job.concurrency_mode
|
34
|
+
assert_equal 'Account', job.object
|
35
|
+
assert_equal 'id', job.external_id_col.name
|
36
|
+
assert_equal ["Id","City","Address","Name", "Number", "Type","State"].sort, job.send(:csv_header).sort
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_csv_columns__unrecognized_column
|
40
|
+
assert_raises Salesforce::UnrecognizedColumn do
|
41
|
+
Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id", [:ssn]).csv_columns
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_csv_columns__unrecognized_column_external_id
|
46
|
+
assert_raises Salesforce::UnrecognizedColumn do
|
47
|
+
Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "ssn").csv_columns
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_bulk_update
|
52
|
+
Salesforce::Bulk::UpsertJob.any_instance.expects(:process!)
|
53
|
+
|
54
|
+
job = Salesforce::BulkTable.bulk_upsert("id") do
|
55
|
+
serial!
|
56
|
+
batch do
|
57
|
+
record({})
|
58
|
+
record({})
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
assert_equal Salesforce::BulkTable, job.object_type
|
63
|
+
assert_equal 'upsert', job.operation
|
64
|
+
assert_equal 'Serial', job.concurrency_mode
|
65
|
+
assert_equal 'BulkTable__c', job.object
|
66
|
+
assert_equal 1, job.batches.size
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_process
|
70
|
+
job = Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id")
|
71
|
+
job.expects(:create_job!)
|
72
|
+
job.expects(:create_batches!)
|
73
|
+
job.expects(:close_job!)
|
74
|
+
job.process!
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_create_job
|
78
|
+
job = Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id")
|
79
|
+
xml = anything
|
80
|
+
Salesforce.connection.expects(:async_post).with("job", xml, :format => :xml).returns({ "id" => 3})
|
81
|
+
job.send :create_job!
|
82
|
+
assert_equal 3, job.id
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_completed
|
86
|
+
job_with_batches
|
87
|
+
@batch_1.stubs(:update_status)
|
88
|
+
@batch_2.stubs(:update_status)
|
89
|
+
@batch_1.expects(:completed?).returns(false)
|
90
|
+
@batch_1.expects(:failed?).returns(false)
|
91
|
+
assert_equal false, @job.completed?
|
92
|
+
|
93
|
+
@batch_1.expects(:completed?).returns(true)
|
94
|
+
@batch_2.expects(:completed?).returns(false)
|
95
|
+
@batch_2.expects(:failed?).returns(false)
|
96
|
+
assert_equal false, @job.completed?
|
97
|
+
|
98
|
+
@batch_1.expects(:completed?).returns(true)
|
99
|
+
@batch_2.expects(:completed?).returns(false)
|
100
|
+
@batch_2.expects(:failed?).returns(true)
|
101
|
+
assert @job.completed?
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_results
|
105
|
+
job_with_batches
|
106
|
+
@batch_1.expects(:results).returns([ :result_1, :result_2])
|
107
|
+
@batch_2.expects(:results).returns([ :result_3, :result_4])
|
108
|
+
assert_equal [ :result_1, :result_2, :result_3, :result_4 ], @job.results
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_close_job
|
112
|
+
Salesforce::Authentication.stubs(:session_id).returns('session_id')
|
113
|
+
job_with_batches
|
114
|
+
Salesforce.connection.expects(:async_post).with("job/jobId", includes("<state>Closed</state>"), :format => :xml).returns("state" => "Closed", "number_batches_total" => 2)
|
115
|
+
@job.send(:close_job!)
|
116
|
+
assert_equal 2, @job.number_batches_total
|
117
|
+
assert @job.closed?
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def job_with_batches
|
123
|
+
Salesforce::Authentication.stubs(:session_id).returns('session_id')
|
124
|
+
|
125
|
+
@job = Salesforce::Bulk::UpsertJob.new(Salesforce::Account, "id")
|
126
|
+
@job.id = "jobId"
|
127
|
+
@batch_1 = Salesforce::Bulk::Batch.new(@job)
|
128
|
+
@batch_2 = Salesforce::Bulk::Batch.new(@job)
|
129
|
+
@job.batches << @batch_1
|
130
|
+
@job.batches << @batch_2
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end
|
metadata
CHANGED
@@ -1,76 +1,97 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: activeforce
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
|
-
authors:
|
6
|
+
authors:
|
7
7
|
- Tushar Ranka
|
8
8
|
- Andrew Mutz
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
16
|
-
type: :runtime
|
12
|
+
date: 2013-08-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
17
15
|
name: rails
|
18
|
-
|
19
|
-
requirements:
|
20
|
-
- -
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version:
|
23
|
-
requirement: *id001
|
24
|
-
prerelease: false
|
25
|
-
- !ruby/object:Gem::Dependency
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '3.0'
|
26
21
|
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
27
29
|
name: savon
|
28
|
-
|
29
|
-
requirements:
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
30
32
|
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version:
|
33
|
-
requirement: *id002
|
34
|
-
prerelease: false
|
35
|
-
- !ruby/object:Gem::Dependency
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.0'
|
36
35
|
type: :runtime
|
37
|
-
name: blockenspiel
|
38
|
-
version_requirements: &id003 !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- &id004
|
41
|
-
- ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: "0"
|
44
|
-
requirement: *id003
|
45
36
|
prerelease: false
|
46
|
-
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: blockenspiel
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
47
49
|
type: :runtime
|
48
|
-
name: rest-client
|
49
|
-
version_requirements: &id005 !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- *id004
|
52
|
-
requirement: *id005
|
53
50
|
prerelease: false
|
54
|
-
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rest-client
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
55
63
|
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
56
71
|
name: fastercsv
|
57
|
-
|
58
|
-
requirements:
|
59
|
-
-
|
60
|
-
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
61
78
|
prerelease: false
|
62
|
-
|
63
|
-
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
description: ' Activeforce provides a simple to use and extend interface to Salesforce
|
85
|
+
using the REST API'
|
86
|
+
email:
|
64
87
|
- tusharranka@gmail.com
|
65
88
|
- andrew.mutz@appfolio.com
|
66
89
|
executables: []
|
67
|
-
|
68
90
|
extensions: []
|
69
|
-
|
70
|
-
extra_rdoc_files:
|
91
|
+
extra_rdoc_files:
|
71
92
|
- LICENSE.txt
|
72
93
|
- README.md
|
73
|
-
files:
|
94
|
+
files:
|
74
95
|
- .gitignore
|
75
96
|
- Gemfile
|
76
97
|
- Gemfile.lock
|
@@ -135,6 +156,7 @@ files:
|
|
135
156
|
- lib/salesforce/bulk/job.rb
|
136
157
|
- lib/salesforce/bulk/operations.rb
|
137
158
|
- lib/salesforce/bulk/update_job.rb
|
159
|
+
- lib/salesforce/bulk/upsert_job.rb
|
138
160
|
- lib/salesforce/column.rb
|
139
161
|
- lib/salesforce/columns.rb
|
140
162
|
- lib/salesforce/config.rb
|
@@ -150,6 +172,7 @@ files:
|
|
150
172
|
- test/salesforce/base_test.rb
|
151
173
|
- test/salesforce/bulk/batch_test.rb
|
152
174
|
- test/salesforce/bulk/update_job_test.rb
|
175
|
+
- test/salesforce/bulk/upsert_job_test.rb
|
153
176
|
- test/salesforce/column_test.rb
|
154
177
|
- test/salesforce/config_test.rb
|
155
178
|
- test/salesforce/connection/async_test.rb
|
@@ -159,27 +182,27 @@ files:
|
|
159
182
|
- test/salesforce/connection_test.rb
|
160
183
|
- test/test_helper.rb
|
161
184
|
homepage: http://github.com/appfolio/activeforce
|
162
|
-
licenses:
|
185
|
+
licenses:
|
163
186
|
- MIT
|
164
187
|
metadata: {}
|
165
|
-
|
166
188
|
post_install_message:
|
167
189
|
rdoc_options: []
|
168
|
-
|
169
|
-
require_paths:
|
190
|
+
require_paths:
|
170
191
|
- lib
|
171
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
172
|
-
requirements:
|
173
|
-
-
|
174
|
-
|
175
|
-
|
176
|
-
|
192
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - '>='
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
177
202
|
requirements: []
|
178
|
-
|
179
203
|
rubyforge_project:
|
180
|
-
rubygems_version: 2.
|
204
|
+
rubygems_version: 2.1.11
|
181
205
|
signing_key:
|
182
206
|
specification_version: 4
|
183
207
|
summary: A Simple gem to interact with the Salesforce REST API
|
184
208
|
test_files: []
|
185
|
-
|