salesforce_bulk 0.0.5 → 0.1.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.
- data/README.rdoc +66 -59
- data/lib/salesforce_bulk.rb +70 -70
- data/lib/salesforce_bulk/connection.rb +92 -91
- data/lib/salesforce_bulk/job.rb +125 -126
- data/lib/salesforce_bulk/version.rb +1 -1
- data/salesforce_bulk.gemspec +27 -27
- metadata +10 -5
data/README.rdoc
CHANGED
@@ -1,59 +1,66 @@
|
|
1
|
-
= salesforce-bulk
|
2
|
-
|
3
|
-
==Overview
|
4
|
-
|
5
|
-
Salesforce bulk is a simple ruby gem for connecting to and using the Salesforce Bulk API (http://www.salesforce.com/us/developer/docs/api_asynch/index.htm). There are already some gems out there that provide connectivity to the Salesforce SOAP and Rest APIs, if your needs are simple, I recommend using those, specifically raygao's asf-rest-adapter (https://github.com/raygao/asf-rest-adapter).
|
6
|
-
|
7
|
-
==How to use
|
8
|
-
|
9
|
-
Using this gem is simple and straight forward.
|
10
|
-
|
11
|
-
To initialize:
|
12
|
-
|
13
|
-
require 'salesforce_bulk'
|
14
|
-
salesforce = SalesforceBulk::Api.new("YOUR_SALESFORCE_USERNAME", "YOUR_SALESFORCE_PASSWORD+YOUR_SALESFORCE_TOKEN")
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
1
|
+
= salesforce-bulk
|
2
|
+
|
3
|
+
==Overview
|
4
|
+
|
5
|
+
Salesforce bulk is a simple ruby gem for connecting to and using the Salesforce Bulk API (http://www.salesforce.com/us/developer/docs/api_asynch/index.htm). There are already some gems out there that provide connectivity to the Salesforce SOAP and Rest APIs, if your needs are simple, I recommend using those, specifically raygao's asf-rest-adapter (https://github.com/raygao/asf-rest-adapter).
|
6
|
+
|
7
|
+
==How to use
|
8
|
+
|
9
|
+
Using this gem is simple and straight forward.
|
10
|
+
|
11
|
+
To initialize:
|
12
|
+
|
13
|
+
require 'salesforce_bulk'
|
14
|
+
salesforce = SalesforceBulk::Api.new("YOUR_SALESFORCE_USERNAME", "YOUR_SALESFORCE_PASSWORD+YOUR_SALESFORCE_TOKEN")
|
15
|
+
|
16
|
+
To use sandbox:
|
17
|
+
salesforce = SalesforceBulk::Api.new("YOUR_SALESFORCE_SANDBOX_USERNAME", "YOUR_SALESFORCE_PASSWORD+YOUR_SALESFORCE_SANDBOX_TOKEN", true)
|
18
|
+
|
19
|
+
Note: the second parameter is a combination of your Salesforce token and password. So if your password is xxxx and your token is yyyy, the second parameter will be xxxxyyyy
|
20
|
+
|
21
|
+
Sample operations:
|
22
|
+
|
23
|
+
# Insert/Create
|
24
|
+
new_account = Hash["name" => "Test Account", "type" => "Other"] # Add as many fields per record as needed.
|
25
|
+
records_to_insert = Array.new
|
26
|
+
records_to_insert.push(new_account) # You can add as many records as you want here, just keep in mind that Salesforce has governor limits.
|
27
|
+
result = salesforce.create("Account", records_to_insert)
|
28
|
+
puts "result is: #{result.inspect}"
|
29
|
+
|
30
|
+
# Update
|
31
|
+
updated_account = Hash["name" => "Test Account -- Updated", id => "a00A0001009zA2m"] # Nearly identical to an insert, but we need to pass the salesforce id.
|
32
|
+
records_to_update = Array.new
|
33
|
+
records_to_update.push(updated_account)
|
34
|
+
salesforce.update("Account", records_to_update)
|
35
|
+
|
36
|
+
# Upsert
|
37
|
+
upserted_account = Hash["name" => "Test Account -- Upserted", "External_Field_Name" => "123456"] # Fields to be updated. External field must be included
|
38
|
+
records_to_upsert = Array.new
|
39
|
+
records_to_upsert.push(upserted_account)
|
40
|
+
salesforce.upsert("Account", records_to_upsert, "External_Field_Name") # Note that upsert accepts an extra parameter for the external field name
|
41
|
+
|
42
|
+
OR
|
43
|
+
|
44
|
+
salesforce.upsert("Account", records_to_upsert, "External_Field_Name", true) # last parameter indicates whether to wait until the batch finishes
|
45
|
+
|
46
|
+
# Delete
|
47
|
+
deleted_account = Hash["id" => "a00A0001009zA2m"] # We only specify the id of the records to delete
|
48
|
+
records_to_delete = Array.new
|
49
|
+
records_to_delete.push(deleted_account)
|
50
|
+
salesforce.delete("Account", records_to_delete)
|
51
|
+
|
52
|
+
# Query
|
53
|
+
res = salesforce.query("Account", "select id, name, createddate from Account limit 3") # We just need to pass the sobject name and the query string
|
54
|
+
|
55
|
+
==Installation
|
56
|
+
sudo gem install salesforce_bulk
|
57
|
+
|
58
|
+
==TODO
|
59
|
+
This is a rough early version of the gem. Immediate plans include better error reporting as there currently is none.
|
60
|
+
|
61
|
+
== Copyright
|
62
|
+
|
63
|
+
Copyright (c) 2011 Jorge Valdivia.
|
64
|
+
|
65
|
+
===end
|
66
|
+
|
data/lib/salesforce_bulk.rb
CHANGED
@@ -1,70 +1,70 @@
|
|
1
|
-
require 'net/https'
|
2
|
-
require 'xmlsimple'
|
3
|
-
require 'csv'
|
4
|
-
require "salesforce_bulk/version"
|
5
|
-
require 'salesforce_bulk/job'
|
6
|
-
require 'salesforce_bulk/connection'
|
7
|
-
|
8
|
-
module SalesforceBulk
|
9
|
-
# Your code goes here...
|
10
|
-
class Api
|
11
|
-
|
12
|
-
@@SALESFORCE_API_VERSION = '
|
13
|
-
|
14
|
-
def initialize(username, password)
|
15
|
-
@connection = SalesforceBulk::Connection.new(username, password, @@SALESFORCE_API_VERSION)
|
16
|
-
end
|
17
|
-
|
18
|
-
def upsert(sobject, records, external_field)
|
19
|
-
self.do_operation('upsert', sobject, records, external_field)
|
20
|
-
end
|
21
|
-
|
22
|
-
def update(sobject, records)
|
23
|
-
self.do_operation('update', sobject, records, nil)
|
24
|
-
end
|
25
|
-
|
26
|
-
def create(sobject, records)
|
27
|
-
self.do_operation('insert', sobject, records, nil)
|
28
|
-
end
|
29
|
-
|
30
|
-
def delete(sobject, records)
|
31
|
-
self.do_operation('delete', sobject, records, nil)
|
32
|
-
end
|
33
|
-
|
34
|
-
def query(sobject, query)
|
35
|
-
self.do_operation('query', sobject, query, nil)
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
batch_id = job.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end # End class
|
70
|
-
end
|
1
|
+
require 'net/https'
|
2
|
+
require 'xmlsimple'
|
3
|
+
require 'csv'
|
4
|
+
require "salesforce_bulk/version"
|
5
|
+
require 'salesforce_bulk/job'
|
6
|
+
require 'salesforce_bulk/connection'
|
7
|
+
|
8
|
+
module SalesforceBulk
|
9
|
+
# Your code goes here...
|
10
|
+
class Api
|
11
|
+
|
12
|
+
@@SALESFORCE_API_VERSION = '24.0'
|
13
|
+
|
14
|
+
def initialize(username, password, in_sandbox=false)
|
15
|
+
@connection = SalesforceBulk::Connection.new(username, password, @@SALESFORCE_API_VERSION, in_sandbox)
|
16
|
+
end
|
17
|
+
|
18
|
+
def upsert(sobject, records, external_field, wait=false)
|
19
|
+
self.do_operation('upsert', sobject, records, external_field, wait)
|
20
|
+
end
|
21
|
+
|
22
|
+
def update(sobject, records)
|
23
|
+
self.do_operation('update', sobject, records, nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
def create(sobject, records)
|
27
|
+
self.do_operation('insert', sobject, records, nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(sobject, records)
|
31
|
+
self.do_operation('delete', sobject, records, nil)
|
32
|
+
end
|
33
|
+
|
34
|
+
def query(sobject, query)
|
35
|
+
self.do_operation('query', sobject, query, nil)
|
36
|
+
end
|
37
|
+
|
38
|
+
def do_operation(operation, sobject, records, external_field, wait=false)
|
39
|
+
job = SalesforceBulk::Job.new(operation, sobject, records, external_field, @connection)
|
40
|
+
|
41
|
+
# TODO: put this in one function
|
42
|
+
job_id = job.create_job()
|
43
|
+
if(operation == "query")
|
44
|
+
batch_id = job.add_query()
|
45
|
+
else
|
46
|
+
batch_id = job.add_batch()
|
47
|
+
end
|
48
|
+
job.close_job()
|
49
|
+
|
50
|
+
if wait or operation == 'query'
|
51
|
+
while true
|
52
|
+
state = job.check_batch_status()
|
53
|
+
#puts "\nstate is #{state}\n"
|
54
|
+
if state != "Queued" && state != "InProgress"
|
55
|
+
break
|
56
|
+
end
|
57
|
+
sleep(2) # wait x seconds and check again
|
58
|
+
end
|
59
|
+
|
60
|
+
if state == 'Completed'
|
61
|
+
job.get_batch_result()
|
62
|
+
else
|
63
|
+
return "There is an error in your job."
|
64
|
+
end
|
65
|
+
else
|
66
|
+
return "The job has been closed."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end # End class
|
70
|
+
end # End module
|
@@ -1,91 +1,92 @@
|
|
1
|
-
module SalesforceBulk
|
2
|
-
|
3
|
-
class Connection
|
4
|
-
|
5
|
-
@@XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>'
|
6
|
-
@@API_VERSION = nil
|
7
|
-
@@LOGIN_HOST = 'login.salesforce.com'
|
8
|
-
@@INSTANCE_HOST = nil # Gets set in login()
|
9
|
-
|
10
|
-
def initialize(username, password, api_version)
|
11
|
-
@username = username
|
12
|
-
@password = password
|
13
|
-
@session_id = nil
|
14
|
-
@server_url = nil
|
15
|
-
@instance = nil
|
16
|
-
@@API_VERSION = api_version
|
17
|
-
@@LOGIN_PATH = "/services/Soap/u/#{@@API_VERSION}"
|
18
|
-
@@PATH_PREFIX = "/services/async/#{@@API_VERSION}/"
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
xml
|
29
|
-
xml += "
|
30
|
-
xml += " xmlns:
|
31
|
-
xml += "
|
32
|
-
xml += "
|
33
|
-
xml += "
|
34
|
-
xml += " <n1:
|
35
|
-
xml += "
|
36
|
-
xml += "
|
37
|
-
xml += "</env:
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
@
|
46
|
-
@
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
req
|
80
|
-
req.
|
81
|
-
req
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
@
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
1
|
+
module SalesforceBulk
|
2
|
+
|
3
|
+
class Connection
|
4
|
+
|
5
|
+
@@XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>'
|
6
|
+
@@API_VERSION = nil
|
7
|
+
@@LOGIN_HOST = 'login.salesforce.com'
|
8
|
+
@@INSTANCE_HOST = nil # Gets set in login()
|
9
|
+
|
10
|
+
def initialize(username, password, api_version, in_sandbox)
|
11
|
+
@username = username
|
12
|
+
@password = password
|
13
|
+
@session_id = nil
|
14
|
+
@server_url = nil
|
15
|
+
@instance = nil
|
16
|
+
@@API_VERSION = api_version
|
17
|
+
@@LOGIN_PATH = "/services/Soap/u/#{@@API_VERSION}"
|
18
|
+
@@PATH_PREFIX = "/services/async/#{@@API_VERSION}/"
|
19
|
+
@@LOGIN_HOST = 'test.salesforce.com' if in_sandbox
|
20
|
+
|
21
|
+
login()
|
22
|
+
end
|
23
|
+
|
24
|
+
#private
|
25
|
+
|
26
|
+
def login()
|
27
|
+
|
28
|
+
xml = '<?xml version="1.0" encoding="utf-8" ?>'
|
29
|
+
xml += "<env:Envelope xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
|
30
|
+
xml += " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
|
31
|
+
xml += " xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">"
|
32
|
+
xml += " <env:Body>"
|
33
|
+
xml += " <n1:login xmlns:n1=\"urn:partner.soap.sforce.com\">"
|
34
|
+
xml += " <n1:username>#{@username}</n1:username>"
|
35
|
+
xml += " <n1:password>#{@password}</n1:password>"
|
36
|
+
xml += " </n1:login>"
|
37
|
+
xml += " </env:Body>"
|
38
|
+
xml += "</env:Envelope>"
|
39
|
+
|
40
|
+
headers = Hash['Content-Type' => 'text/xml; charset=utf-8', 'SOAPAction' => 'login']
|
41
|
+
|
42
|
+
response = post_xml(@@LOGIN_HOST, @@LOGIN_PATH, xml, headers)
|
43
|
+
response_parsed = XmlSimple.xml_in(response)
|
44
|
+
|
45
|
+
@session_id = response_parsed['Body'][0]['loginResponse'][0]['result'][0]['sessionId'][0]
|
46
|
+
@server_url = response_parsed['Body'][0]['loginResponse'][0]['result'][0]['serverUrl'][0]
|
47
|
+
@instance = parse_instance()
|
48
|
+
|
49
|
+
@@INSTANCE_HOST = "#{@instance}.salesforce.com"
|
50
|
+
end
|
51
|
+
|
52
|
+
def post_xml(host, path, xml, headers)
|
53
|
+
|
54
|
+
host = host || @@INSTANCE_HOST
|
55
|
+
|
56
|
+
if host != @@LOGIN_HOST # Not login, need to add session id to header
|
57
|
+
headers['X-SFDC-Session'] = @session_id;
|
58
|
+
#puts "session id is: #{@session_id} --- #{headers.inspect}\n"
|
59
|
+
path = "#{@@PATH_PREFIX}#{path}"
|
60
|
+
end
|
61
|
+
|
62
|
+
#puts "#{host} -- #{path} -- #{headers.inspect}\n"
|
63
|
+
|
64
|
+
https(host).post(path, xml, headers).body
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_request(host, path, headers)
|
68
|
+
host = host || @@INSTANCE_HOST
|
69
|
+
path = "#{@@PATH_PREFIX}#{path}"
|
70
|
+
|
71
|
+
if host != @@LOGIN_HOST # Not login, need to add session id to header
|
72
|
+
headers['X-SFDC-Session'] = @session_id;
|
73
|
+
end
|
74
|
+
|
75
|
+
https(host).get(path, headers).body
|
76
|
+
end
|
77
|
+
|
78
|
+
def https(host)
|
79
|
+
req = Net::HTTP.new(host, 443)
|
80
|
+
req.use_ssl = true
|
81
|
+
req.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
82
|
+
req
|
83
|
+
end
|
84
|
+
|
85
|
+
def parse_instance()
|
86
|
+
@server_url =~ /https:\/\/([a-z]{2,2}[0-9]{1,2})-api/
|
87
|
+
@instance = $~.captures[0]
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
data/lib/salesforce_bulk/job.rb
CHANGED
@@ -1,126 +1,125 @@
|
|
1
|
-
module SalesforceBulk
|
2
|
-
|
3
|
-
class Job
|
4
|
-
|
5
|
-
def initialize(operation, sobject, records, external_field, connection)
|
6
|
-
|
7
|
-
@@operation = operation
|
8
|
-
@@sobject = sobject
|
9
|
-
@@external_field = external_field
|
10
|
-
@@records = records
|
11
|
-
@@connection = connection
|
12
|
-
@@XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>'
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
def create_job()
|
17
|
-
xml = "#{@@XML_HEADER}<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">"
|
18
|
-
xml += "<operation>#{@@operation}</operation>"
|
19
|
-
xml += "<object>#{@@sobject}</object>"
|
20
|
-
if !@@external_field.nil? # This only happens on upsert
|
21
|
-
xml += "<externalIdFieldName>#{@@external_field}</externalIdFieldName>"
|
22
|
-
end
|
23
|
-
xml += "<contentType>CSV</contentType>"
|
24
|
-
xml += "</jobInfo>"
|
25
|
-
|
26
|
-
path = "job"
|
27
|
-
headers = Hash['Content-Type' => 'application/xml; charset=utf-8']
|
28
|
-
|
29
|
-
response = @@connection.post_xml(nil, path, xml, headers)
|
30
|
-
response_parsed = XmlSimple.xml_in(response)
|
31
|
-
|
32
|
-
@@job_id = response_parsed['id'][0]
|
33
|
-
end
|
34
|
-
|
35
|
-
def close_job()
|
36
|
-
xml = "#{@@XML_HEADER}<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">"
|
37
|
-
xml += "<state>Closed</state>"
|
38
|
-
xml += "</jobInfo>"
|
39
|
-
|
40
|
-
path = "job/#{@@job_id}"
|
41
|
-
headers = Hash['Content-Type' => 'application/xml; charset=utf-8']
|
42
|
-
|
43
|
-
response = @@connection.post_xml(nil, path, xml, headers)
|
44
|
-
response_parsed = XmlSimple.xml_in(response)
|
45
|
-
|
46
|
-
#job_id = response_parsed['id'][0]
|
47
|
-
end
|
48
|
-
|
49
|
-
def add_query
|
50
|
-
path = "job/#{@@job_id}/batch/"
|
51
|
-
headers = Hash["Content-Type" => "text/csv; charset=UTF-8"]
|
52
|
-
|
53
|
-
response = @@connection.post_xml(nil, path, @@records, headers)
|
54
|
-
response_parsed = XmlSimple.xml_in(response)
|
55
|
-
|
56
|
-
@@batch_id = response_parsed['id'][0]
|
57
|
-
end
|
58
|
-
|
59
|
-
def add_batch()
|
60
|
-
keys = @@records.
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
headers = Hash
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
1
|
+
module SalesforceBulk
|
2
|
+
|
3
|
+
class Job
|
4
|
+
|
5
|
+
def initialize(operation, sobject, records, external_field, connection)
|
6
|
+
|
7
|
+
@@operation = operation
|
8
|
+
@@sobject = sobject
|
9
|
+
@@external_field = external_field
|
10
|
+
@@records = records
|
11
|
+
@@connection = connection
|
12
|
+
@@XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>'
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_job()
|
17
|
+
xml = "#{@@XML_HEADER}<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">"
|
18
|
+
xml += "<operation>#{@@operation}</operation>"
|
19
|
+
xml += "<object>#{@@sobject}</object>"
|
20
|
+
if !@@external_field.nil? # This only happens on upsert
|
21
|
+
xml += "<externalIdFieldName>#{@@external_field}</externalIdFieldName>"
|
22
|
+
end
|
23
|
+
xml += "<contentType>CSV</contentType>"
|
24
|
+
xml += "</jobInfo>"
|
25
|
+
|
26
|
+
path = "job"
|
27
|
+
headers = Hash['Content-Type' => 'application/xml; charset=utf-8']
|
28
|
+
|
29
|
+
response = @@connection.post_xml(nil, path, xml, headers)
|
30
|
+
response_parsed = XmlSimple.xml_in(response)
|
31
|
+
|
32
|
+
@@job_id = response_parsed['id'][0]
|
33
|
+
end
|
34
|
+
|
35
|
+
def close_job()
|
36
|
+
xml = "#{@@XML_HEADER}<jobInfo xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">"
|
37
|
+
xml += "<state>Closed</state>"
|
38
|
+
xml += "</jobInfo>"
|
39
|
+
|
40
|
+
path = "job/#{@@job_id}"
|
41
|
+
headers = Hash['Content-Type' => 'application/xml; charset=utf-8']
|
42
|
+
|
43
|
+
response = @@connection.post_xml(nil, path, xml, headers)
|
44
|
+
response_parsed = XmlSimple.xml_in(response)
|
45
|
+
|
46
|
+
#job_id = response_parsed['id'][0]
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_query
|
50
|
+
path = "job/#{@@job_id}/batch/"
|
51
|
+
headers = Hash["Content-Type" => "text/csv; charset=UTF-8"]
|
52
|
+
|
53
|
+
response = @@connection.post_xml(nil, path, @@records, headers)
|
54
|
+
response_parsed = XmlSimple.xml_in(response)
|
55
|
+
|
56
|
+
@@batch_id = response_parsed['id'][0]
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_batch()
|
60
|
+
keys = @@records.first.keys
|
61
|
+
|
62
|
+
output_csv = keys.to_csv
|
63
|
+
|
64
|
+
@@records.each do |r|
|
65
|
+
fields = Array.new
|
66
|
+
keys.each do |k|
|
67
|
+
fields.push(r[k])
|
68
|
+
end
|
69
|
+
|
70
|
+
row_csv = fields.to_csv
|
71
|
+
output_csv += row_csv
|
72
|
+
end
|
73
|
+
|
74
|
+
path = "job/#{@@job_id}/batch/"
|
75
|
+
headers = Hash["Content-Type" => "text/csv; charset=UTF-8"]
|
76
|
+
|
77
|
+
response = @@connection.post_xml(nil, path, output_csv, headers)
|
78
|
+
response_parsed = XmlSimple.xml_in(response)
|
79
|
+
|
80
|
+
@@batch_id = response_parsed['id'][0]
|
81
|
+
end
|
82
|
+
|
83
|
+
def check_batch_status()
|
84
|
+
path = "job/#{@@job_id}/batch/#{@@batch_id}"
|
85
|
+
headers = Hash.new
|
86
|
+
|
87
|
+
response = @@connection.get_request(nil, path, headers)
|
88
|
+
response_parsed = XmlSimple.xml_in(response)
|
89
|
+
|
90
|
+
begin
|
91
|
+
#puts "check: #{response_parsed.inspect}\n"
|
92
|
+
response_parsed['state'][0]
|
93
|
+
rescue Exception => e
|
94
|
+
#puts "check: #{response_parsed.inspect}\n"
|
95
|
+
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_batch_result()
|
101
|
+
path = "job/#{@@job_id}/batch/#{@@batch_id}/result"
|
102
|
+
headers = Hash["Content-Type" => "text/xml; charset=UTF-8"]
|
103
|
+
|
104
|
+
response = @@connection.get_request(nil, path, headers)
|
105
|
+
|
106
|
+
if(@@operation == "query") # The query op requires us to do another request to get the results
|
107
|
+
response_parsed = XmlSimple.xml_in(response)
|
108
|
+
result_id = response_parsed["result"][0]
|
109
|
+
|
110
|
+
path = "job/#{@@job_id}/batch/#{@@batch_id}/result/#{result_id}"
|
111
|
+
headers = Hash.new
|
112
|
+
headers = Hash["Content-Type" => "text/xml; charset=UTF-8"]
|
113
|
+
#puts "path is: #{path}\n"
|
114
|
+
|
115
|
+
response = @@connection.get_request(nil, path, headers)
|
116
|
+
#puts "\n\nres2: #{response.inspect}\n\n"
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
response = response.lines.to_a[1..-1].join
|
121
|
+
csvRows = CSV.parse(response)
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
data/salesforce_bulk.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "salesforce_bulk/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "salesforce_bulk"
|
7
|
-
s.version = SalesforceBulk::VERSION
|
8
|
-
s.authors = ["Jorge Valdivia"]
|
9
|
-
s.email = ["jorge@valdivia.me"]
|
10
|
-
s.homepage = "https://github.com/jorgevaldivia/salesforce_bulk"
|
11
|
-
s.summary = %q{Ruby support for the Salesforce Bulk API}
|
12
|
-
s.description = %q{This gem provides a super simple interface for the Salesforce Bulk API. It provides support for insert, update, upsert, delete, and query.}
|
13
|
-
|
14
|
-
s.rubyforge_project = "salesforce_bulk"
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = ["lib"]
|
20
|
-
|
21
|
-
# specify any dependencies here; for example:
|
22
|
-
# s.add_development_dependency "rspec"
|
23
|
-
# s.add_runtime_dependency "rest-client"
|
24
|
-
|
25
|
-
s.add_dependency "xml-simple"
|
26
|
-
|
27
|
-
end
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "salesforce_bulk/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "salesforce_bulk"
|
7
|
+
s.version = SalesforceBulk::VERSION
|
8
|
+
s.authors = ["Jorge Valdivia"]
|
9
|
+
s.email = ["jorge@valdivia.me"]
|
10
|
+
s.homepage = "https://github.com/jorgevaldivia/salesforce_bulk"
|
11
|
+
s.summary = %q{Ruby support for the Salesforce Bulk API}
|
12
|
+
s.description = %q{This gem provides a super simple interface for the Salesforce Bulk API. It provides support for insert, update, upsert, delete, and query.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "salesforce_bulk"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
|
25
|
+
s.add_dependency "xml-simple"
|
26
|
+
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: salesforce_bulk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: xml-simple
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,12 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
description: This gem provides a super simple interface for the Salesforce Bulk API.
|
26
31
|
It provides support for insert, update, upsert, delete, and query.
|
27
32
|
email:
|
@@ -59,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
64
|
version: '0'
|
60
65
|
requirements: []
|
61
66
|
rubyforge_project: salesforce_bulk
|
62
|
-
rubygems_version: 1.8.
|
67
|
+
rubygems_version: 1.8.22
|
63
68
|
signing_key:
|
64
69
|
specification_version: 3
|
65
70
|
summary: Ruby support for the Salesforce Bulk API
|