salesforce_bulk 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|