salesforce_bulk 0.1.0 → 1.0.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 CHANGED
@@ -2,8 +2,12 @@
2
2
 
3
3
  ==Overview
4
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).
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) or databasedotcom (https://rubygems.org/gems/databasedotcom).
6
6
 
7
+ ==Installation
8
+
9
+ sudo gem install salesforce_bulk
10
+
7
11
  ==How to use
8
12
 
9
13
  Using this gem is simple and straight forward.
@@ -28,7 +32,7 @@ Sample operations:
28
32
  puts "result is: #{result.inspect}"
29
33
 
30
34
  # Update
31
- updated_account = Hash["name" => "Test Account -- Updated", id => "a00A0001009zA2m"] # Nearly identical to an insert, but we need to pass the salesforce id.
35
+ updated_account = Hash["name" => "Test Account -- Updated", "id" => "a00A0001009zA2m"] # Nearly identical to an insert, but we need to pass the salesforce id.
32
36
  records_to_update = Array.new
33
37
  records_to_update.push(updated_account)
34
38
  salesforce.update("Account", records_to_update)
@@ -51,16 +55,21 @@ Sample operations:
51
55
 
52
56
  # Query
53
57
  res = salesforce.query("Account", "select id, name, createddate from Account limit 3") # We just need to pass the sobject name and the query string
58
+ puts res.records.inspect
54
59
 
55
- ==Installation
56
- sudo gem install salesforce_bulk
60
+ Result reporting:
57
61
 
58
- ==TODO
59
- This is a rough early version of the gem. Immediate plans include better error reporting as there currently is none.
62
+ new_account = Hash["type" => "Other"] # Missing required field "name."
63
+ records_to_insert = Array.new
64
+ 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.
65
+ result = salesforce.create("Account", records_to_insert)
66
+ puts result.success? # false
67
+ puts result.has_errors? # true
68
+ puts result.errors # An indexed hash detailing the errors
60
69
 
61
70
  == Copyright
62
71
 
63
- Copyright (c) 2011 Jorge Valdivia.
72
+ Copyright (c) 2012 Jorge Valdivia.
64
73
 
65
74
  ===end
66
75
 
@@ -19,16 +19,16 @@ module SalesforceBulk
19
19
  self.do_operation('upsert', sobject, records, external_field, wait)
20
20
  end
21
21
 
22
- def update(sobject, records)
23
- self.do_operation('update', sobject, records, nil)
22
+ def update(sobject, records, wait=false)
23
+ self.do_operation('update', sobject, records, nil, wait)
24
24
  end
25
25
 
26
- def create(sobject, records)
27
- self.do_operation('insert', sobject, records, nil)
26
+ def create(sobject, records, wait=false)
27
+ self.do_operation('insert', sobject, records, nil, wait)
28
28
  end
29
29
 
30
- def delete(sobject, records)
31
- self.do_operation('delete', sobject, records, nil)
30
+ def delete(sobject, records, wait=false)
31
+ self.do_operation('delete', sobject, records, nil, wait)
32
32
  end
33
33
 
34
34
  def query(sobject, query)
@@ -50,7 +50,6 @@ module SalesforceBulk
50
50
  if wait or operation == 'query'
51
51
  while true
52
52
  state = job.check_batch_status()
53
- #puts "\nstate is #{state}\n"
54
53
  if state != "Queued" && state != "InProgress"
55
54
  break
56
55
  end
@@ -59,12 +58,26 @@ module SalesforceBulk
59
58
 
60
59
  if state == 'Completed'
61
60
  job.get_batch_result()
61
+ job
62
62
  else
63
- return "There is an error in your job."
63
+ job.result.message = "There is an error in your job. The response returned a state of #{state}. Please check your query/parameters and try again."
64
+ job.result.success = false
65
+ return job
66
+
64
67
  end
65
68
  else
66
- return "The job has been closed."
69
+ return job
70
+ end
71
+
72
+ end
73
+
74
+ def parse_batch_result result
75
+ begin
76
+ CSV.parse(result, :headers => true)
77
+ rescue
78
+ result
67
79
  end
68
80
  end
81
+
69
82
  end # End class
70
83
  end # End module
@@ -40,7 +40,8 @@ module SalesforceBulk
40
40
  headers = Hash['Content-Type' => 'text/xml; charset=utf-8', 'SOAPAction' => 'login']
41
41
 
42
42
  response = post_xml(@@LOGIN_HOST, @@LOGIN_PATH, xml, headers)
43
- response_parsed = XmlSimple.xml_in(response)
43
+ # response_parsed = XmlSimple.xml_in(response)
44
+ response_parsed = parse_response response
44
45
 
45
46
  @session_id = response_parsed['Body'][0]['loginResponse'][0]['result'][0]['sessionId'][0]
46
47
  @server_url = response_parsed['Body'][0]['loginResponse'][0]['result'][0]['serverUrl'][0]
@@ -55,12 +56,9 @@ module SalesforceBulk
55
56
 
56
57
  if host != @@LOGIN_HOST # Not login, need to add session id to header
57
58
  headers['X-SFDC-Session'] = @session_id;
58
- #puts "session id is: #{@session_id} --- #{headers.inspect}\n"
59
59
  path = "#{@@PATH_PREFIX}#{path}"
60
60
  end
61
61
 
62
- #puts "#{host} -- #{path} -- #{headers.inspect}\n"
63
-
64
62
  https(host).post(path, xml, headers).body
65
63
  end
66
64
 
@@ -87,6 +85,28 @@ module SalesforceBulk
87
85
  @instance = $~.captures[0]
88
86
  end
89
87
 
88
+ def parse_response response
89
+ response_parsed = XmlSimple.xml_in(response)
90
+
91
+ if response.downcase.include?("faultstring") || response.downcase.include?("exceptionmessage")
92
+ begin
93
+
94
+ if response.downcase.include?("faultstring")
95
+ error_message = response_parsed["Body"][0]["Fault"][0]["faultstring"][0]
96
+ elsif response.downcase.include?("exceptionmessage")
97
+ error_message = response_parsed["exceptionMessage"][0]
98
+ end
99
+
100
+ rescue
101
+ raise "An unknown error has occured within the salesforce_bulk gem. This is most likely caused by bad request, but I am unable to parse the correct error message. Here is a dump of the response for your convenience. #{response}"
102
+ end
103
+
104
+ raise error_message
105
+ end
106
+
107
+ response_parsed
108
+ end
109
+
90
110
  end
91
111
 
92
112
  end
@@ -2,6 +2,8 @@ module SalesforceBulk
2
2
 
3
3
  class Job
4
4
 
5
+ attr :result
6
+
5
7
  def initialize(operation, sobject, records, external_field, connection)
6
8
 
7
9
  @@operation = operation
@@ -11,6 +13,9 @@ module SalesforceBulk
11
13
  @@connection = connection
12
14
  @@XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>'
13
15
 
16
+ # @result = {"errors" => [], "success" => nil, "records" => [], "raw" => nil, "message" => 'The job has been queued.'}
17
+ @result = JobResult.new
18
+
14
19
  end
15
20
 
16
21
  def create_job()
@@ -27,7 +32,7 @@ module SalesforceBulk
27
32
  headers = Hash['Content-Type' => 'application/xml; charset=utf-8']
28
33
 
29
34
  response = @@connection.post_xml(nil, path, xml, headers)
30
- response_parsed = XmlSimple.xml_in(response)
35
+ response_parsed = @@connection.parse_response response
31
36
 
32
37
  @@job_id = response_parsed['id'][0]
33
38
  end
@@ -110,16 +115,60 @@ module SalesforceBulk
110
115
  path = "job/#{@@job_id}/batch/#{@@batch_id}/result/#{result_id}"
111
116
  headers = Hash.new
112
117
  headers = Hash["Content-Type" => "text/xml; charset=UTF-8"]
113
- #puts "path is: #{path}\n"
114
118
 
115
119
  response = @@connection.get_request(nil, path, headers)
116
- #puts "\n\nres2: #{response.inspect}\n\n"
117
120
 
118
121
  end
119
122
 
123
+ parse_results response
124
+
120
125
  response = response.lines.to_a[1..-1].join
121
- csvRows = CSV.parse(response)
126
+ # csvRows = CSV.parse(response, :headers => true)
122
127
  end
123
128
 
129
+ def parse_results response
130
+ @result.success = true
131
+ @result.raw = response.lines.to_a[1..-1].join
132
+ csvRows = CSV.parse(response, :headers => true)
133
+
134
+ csvRows.each_with_index do |row, index|
135
+ if @@operation != "query"
136
+ row["Created"] = row["Created"] == "true" ? true : false
137
+ row["Success"] = row["Success"] == "true" ? true : false
138
+ end
139
+
140
+ @result.records.push row
141
+ if row["Success"] == false
142
+ @result.success = false
143
+ @result.errors.push({"#{index}" => row["Error"]}) if row["Error"]
144
+ end
145
+ end
146
+
147
+ @result.message = "The job has been closed."
148
+
149
+ end
150
+
151
+ end
152
+
153
+ class JobResult
154
+ attr_writer :errors, :success, :records, :raw, :message
155
+ attr_reader :errors, :success, :records, :raw, :message
156
+
157
+ def initialize
158
+ @errors = []
159
+ @success = nil
160
+ @records = []
161
+ @raw = nil
162
+ @message = 'The job has been queued.'
163
+ end
164
+
165
+ def success?
166
+ @success
167
+ end
168
+
169
+ def has_errors?
170
+ @errors.count > 0
171
+ end
124
172
  end
173
+
125
174
  end
@@ -1,3 +1,3 @@
1
1
  module SalesforceBulk
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.0"
3
3
  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.1.0
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: