activesalesforce 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/asf_adapter.rb +41 -46
- data/lib/result_array.rb +34 -0
- data/lib/rforce.rb +90 -79
- data/test/unit/basic_test.rb +40 -4
- data/test/unit/profiler_results.txt +1072 -0
- data/test/unit/profiler_results_live.txt +1347 -0
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_add_notes_to_contact.recording +1050 -1017
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_assignment_rule_id.recording +1078 -0
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_batch_insert.recording +674 -644
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_count_contacts.recording +770 -708
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_create_a_contact.recording +731 -706
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_a_contact.recording +741 -716
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_a_contact_by_first_name.recording +1026 -764
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_a_contact_by_id.recording +791 -764
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_addresses.recording +1297 -0
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_get_created_by_from_contact.recording +2325 -2280
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_master_detail.recording +1315 -1302
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_read_all_content_columns.recording +691 -666
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_save_a_contact.recording +741 -716
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_use_default_rule.recording +1078 -0
- data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_use_update_mru.recording +1078 -0
- data/test/unit/recorded_test_case.rb +1 -4
- data/test/unit/test.html +157 -0
- data/test/unit/test.html~ +183 -0
- metadata +26 -18
- data/test/unit/recorded_results/AsfUnitTestsAsfScaffoldGeneratorTest.test_describe_layout.recording +0 -1789
data/lib/asf_adapter.rb
CHANGED
@@ -30,15 +30,7 @@ require File.dirname(__FILE__) + '/asf_active_record'
|
|
30
30
|
require File.dirname(__FILE__) + '/id_resolver'
|
31
31
|
require File.dirname(__FILE__) + '/sid_authentication_filter'
|
32
32
|
require File.dirname(__FILE__) + '/recording_binding'
|
33
|
-
|
34
|
-
|
35
|
-
class ResultArray < Array
|
36
|
-
attr_reader :actual_size
|
37
|
-
|
38
|
-
def initialize(actual_size)
|
39
|
-
@actual_size = actual_size
|
40
|
-
end
|
41
|
-
end
|
33
|
+
require File.dirname(__FILE__) + '/result_array'
|
42
34
|
|
43
35
|
|
44
36
|
module ActiveRecord
|
@@ -262,11 +254,9 @@ module ActiveRecord
|
|
262
254
|
end
|
263
255
|
|
264
256
|
raw_table_name = sql.match(/FROM (\w+)/i)[1]
|
265
|
-
table_name = raw_table_name
|
266
|
-
entity_name = entity_name_from_table(table_name)
|
267
|
-
entity_def = get_entity_def(entity_name)
|
257
|
+
table_name, columns, entity_def = lookup(raw_table_name)
|
268
258
|
|
269
|
-
column_names =
|
259
|
+
column_names = columns.map { |column| column.api_name }
|
270
260
|
|
271
261
|
# Always (unless COUNT*)'ing) select all columns (required for the AR attributes mechanism to work correctly
|
272
262
|
soql = sql.sub(/SELECT .+ FROM/i, "SELECT #{column_names.join(', ')} FROM") unless selectCountMatch
|
@@ -274,13 +264,13 @@ module ActiveRecord
|
|
274
264
|
soql.sub!(/\s+FROM\s+\w+/i, " FROM #{entity_def.api_name}")
|
275
265
|
|
276
266
|
# Look for a LIMIT clause
|
277
|
-
soql
|
267
|
+
limit = extract_sql_modifier(soql, "LIMIT")
|
278
268
|
|
279
269
|
# Look for an OFFSET clause
|
280
|
-
soql
|
270
|
+
offset = extract_sql_modifier(soql, "OFFSET")
|
281
271
|
|
282
272
|
# Fixup column references to use api names
|
283
|
-
columns =
|
273
|
+
columns = entity_def.column_name_to_column
|
284
274
|
soql.gsub!(/((?:\w+\.)?\w+)(?=\s*(?:=|!=|<|>|<=|>=)\s*(?:'[^']*'|NULL|TRUE|FALSE))/mi) do |column_name|
|
285
275
|
# strip away any table alias
|
286
276
|
column_name.sub!(/\w+\./, '')
|
@@ -295,12 +285,14 @@ module ActiveRecord
|
|
295
285
|
soql.sub!(/#{raw_table_name}\./i, "#{entity_def.api_name}.")
|
296
286
|
|
297
287
|
@connection.batch_size = @batch_size if @batch_size
|
288
|
+
@connection.batch_size = limit if limit
|
289
|
+
|
298
290
|
@batch_size = nil
|
299
291
|
|
300
292
|
queryResult = get_result(@connection.query(:queryString => soql), :query)
|
301
293
|
records = queryResult[:records]
|
302
294
|
|
303
|
-
result = ResultArray.new(queryResult[:size].to_i)
|
295
|
+
result = ActiveSalesforce::ResultArray.new(queryResult[:size].to_i)
|
304
296
|
return result unless records
|
305
297
|
|
306
298
|
records = [ records ] unless records.is_a?(Array)
|
@@ -324,7 +316,10 @@ module ActiveRecord
|
|
324
316
|
end
|
325
317
|
end
|
326
318
|
|
327
|
-
result << row
|
319
|
+
result << row
|
320
|
+
|
321
|
+
# Insure that only LIMIT rows are returned
|
322
|
+
break if limit and result.length >= limit
|
328
323
|
end
|
329
324
|
|
330
325
|
if selectCountMatch
|
@@ -348,9 +343,8 @@ module ActiveRecord
|
|
348
343
|
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
349
344
|
log(sql, name) {
|
350
345
|
# Convert sql to sobject
|
351
|
-
table_name = sql.match(/INSERT\s+INTO\s+(\w+)\s+/i)[1]
|
352
|
-
|
353
|
-
columns = columns_map(table_name)
|
346
|
+
table_name, columns, entity_def = lookup(sql.match(/INSERT\s+INTO\s+(\w+)\s+/i)[1])
|
347
|
+
columns = entity_def.column_name_to_column
|
354
348
|
|
355
349
|
# Extract array of column names
|
356
350
|
names = sql.match(/\((.+)\)\s+VALUES/i)[1].scan(/\w+/i)
|
@@ -363,7 +357,7 @@ module ActiveRecord
|
|
363
357
|
|
364
358
|
fields = get_fields(columns, names, values, :createable)
|
365
359
|
|
366
|
-
sobject = create_sobject(
|
360
|
+
sobject = create_sobject(entity_def.api_name, nil, fields)
|
367
361
|
|
368
362
|
# Track the id to be able to update it when the create() is actually executed
|
369
363
|
id = String.new
|
@@ -377,9 +371,8 @@ module ActiveRecord
|
|
377
371
|
def update(sql, name = nil) #:nodoc:
|
378
372
|
log(sql, name) {
|
379
373
|
# Convert sql to sobject
|
380
|
-
table_name = sql.match(/UPDATE\s+(\w+)\s+/i)[1]
|
381
|
-
|
382
|
-
columns = columns_map(table_name)
|
374
|
+
table_name, columns, entity_def = lookup(sql.match(/UPDATE\s+(\w+)\s+/i)[1])
|
375
|
+
columns = entity_def.column_name_to_column
|
383
376
|
|
384
377
|
match = sql.match(/SET\s+(.+)\s+WHERE/mi)[1]
|
385
378
|
names = match.scan(/(\w+)\s*=\s*('|NULL|TRUE|FALSE)/i)
|
@@ -392,7 +385,7 @@ module ActiveRecord
|
|
392
385
|
|
393
386
|
id = sql.match(/WHERE\s+id\s*=\s*'(\w+)'/i)[1]
|
394
387
|
|
395
|
-
sobject = create_sobject(
|
388
|
+
sobject = create_sobject(entity_def.api_name, id, fields)
|
396
389
|
|
397
390
|
@command_boxcar << ActiveSalesforce::BoxcarCommand::Update.new(self, sobject)
|
398
391
|
}
|
@@ -468,6 +461,17 @@ module ActiveRecord
|
|
468
461
|
end
|
469
462
|
|
470
463
|
|
464
|
+
def extract_sql_modifier(soql, modifier)
|
465
|
+
value = soql.match(/\s+#{modifier}\s+(\d+)/i)
|
466
|
+
if value
|
467
|
+
value = value[1].to_i
|
468
|
+
soql.sub!(/\s+#{modifier}\s+\d+/i, "")
|
469
|
+
end
|
470
|
+
|
471
|
+
value
|
472
|
+
end
|
473
|
+
|
474
|
+
|
471
475
|
def get_result(response, method)
|
472
476
|
responseName = (method.to_s + "Response").to_sym
|
473
477
|
finalResponse = response[responseName]
|
@@ -538,7 +542,7 @@ module ActiveRecord
|
|
538
542
|
key_prefix = metadata[:keyPrefix]
|
539
543
|
|
540
544
|
entity_def = ActiveSalesforce::EntityDefinition.new(self, entity_name,
|
541
|
-
|
545
|
+
cached_columns, cached_relationships, custom, key_prefix)
|
542
546
|
|
543
547
|
@entity_def_map[entity_name] = entity_def
|
544
548
|
@keyprefix_to_entity_def_map[key_prefix] = entity_def
|
@@ -613,19 +617,8 @@ module ActiveRecord
|
|
613
617
|
|
614
618
|
|
615
619
|
def columns(table_name, name = nil)
|
616
|
-
|
617
|
-
|
618
|
-
end
|
619
|
-
|
620
|
-
|
621
|
-
def columns_map(table_name, name = nil)
|
622
|
-
entity_name = entity_name_from_table(table_name)
|
623
|
-
get_entity_def(entity_name).column_name_to_column
|
624
|
-
end
|
625
|
-
|
626
|
-
|
627
|
-
def entity_name_from_table(table_name)
|
628
|
-
return table_name.singularize.camelize
|
620
|
+
table_name, columns, entity_def = lookup(table_name)
|
621
|
+
entity_def.columns
|
629
622
|
end
|
630
623
|
|
631
624
|
|
@@ -640,11 +633,9 @@ module ActiveRecord
|
|
640
633
|
|
641
634
|
|
642
635
|
def create_sobject(entity_name, id, fields)
|
643
|
-
entity_def = get_entity_def(entity_name)
|
644
|
-
|
645
636
|
sobj = []
|
646
637
|
|
647
|
-
sobj << 'type { :xmlns => "urn:sobject.partner.soap.sforce.com" }' <<
|
638
|
+
sobj << 'type { :xmlns => "urn:sobject.partner.soap.sforce.com" }' << entity_name
|
648
639
|
sobj << 'Id { :xmlns => "urn:sobject.partner.soap.sforce.com" }' << id if id
|
649
640
|
|
650
641
|
# now add any changed fields
|
@@ -660,10 +651,14 @@ module ActiveRecord
|
|
660
651
|
def column_names(table_name)
|
661
652
|
columns(table_name).map { |column| column.name }
|
662
653
|
end
|
654
|
+
|
663
655
|
|
664
|
-
|
665
|
-
|
666
|
-
|
656
|
+
def lookup(raw_table_name)
|
657
|
+
table_name = raw_table_name.singularize
|
658
|
+
entity_def = get_entity_def(table_name.camelize)
|
659
|
+
columns = entity_def.columns
|
660
|
+
|
661
|
+
[table_name, columns, entity_def]
|
667
662
|
end
|
668
663
|
|
669
664
|
end
|
data/lib/result_array.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
=begin
|
2
|
+
ActiveSalesforce
|
3
|
+
Copyright 2006 Doug Chasman
|
4
|
+
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
you may not use this file except in compliance with the License.
|
7
|
+
You may obtain a copy of the License at
|
8
|
+
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
See the License for the specific language governing permissions and
|
15
|
+
limitations under the License.
|
16
|
+
=end
|
17
|
+
|
18
|
+
require 'rubygems'
|
19
|
+
require_gem 'rails', ">= 1.0.0"
|
20
|
+
|
21
|
+
require 'pp'
|
22
|
+
|
23
|
+
|
24
|
+
module ActiveSalesforce
|
25
|
+
|
26
|
+
class ResultArray < Array
|
27
|
+
attr_reader :actual_size
|
28
|
+
|
29
|
+
def initialize(actual_size)
|
30
|
+
@actual_size = actual_size
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/rforce.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
=begin
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
2
|
+
RForce v0.1
|
3
|
+
Copyright (c) 2005 Ian Dees
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
22
|
=end
|
23
23
|
|
24
24
|
# RForce is a simple Ruby binding to the SalesForce CRM system.
|
@@ -59,7 +59,7 @@ require_gem 'builder'
|
|
59
59
|
|
60
60
|
|
61
61
|
module RForce
|
62
|
-
|
62
|
+
|
63
63
|
#Allows indexing hashes like method calls: hash.key
|
64
64
|
#to supplement the traditional way of indexing: hash[key]
|
65
65
|
module FlashHash
|
@@ -67,50 +67,50 @@ module RForce
|
|
67
67
|
self[method]
|
68
68
|
end
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
#Turns an XML response from the server into a Ruby
|
72
72
|
#object whose methods correspond to nested XML elements.
|
73
73
|
class SoapResponse
|
74
74
|
include FlashHash
|
75
|
-
|
75
|
+
|
76
76
|
#Parses an XML string into structured data.
|
77
77
|
def initialize(content)
|
78
78
|
document = REXML::Document.new content
|
79
79
|
node = REXML::XPath.first document, '//soapenv:Body'
|
80
80
|
@parsed = SoapResponse.parse node
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
#Allows this object to act like a hash (and therefore
|
84
84
|
#as a FlashHash via the include above).
|
85
85
|
def [](symbol)
|
86
86
|
@parsed[symbol]
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
#Digests an XML DOM node into nested Ruby types.
|
90
90
|
def SoapResponse.parse(node)
|
91
91
|
#Convert text nodes into simple strings.
|
92
92
|
return node.text unless node.has_elements?
|
93
|
-
|
93
|
+
|
94
94
|
#Convert nodes with children into FlashHashes.
|
95
95
|
elements = {}
|
96
96
|
class << elements
|
97
97
|
include FlashHash
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
#Add all the element's children to the hash.
|
101
101
|
node.each_element do |e|
|
102
102
|
name = e.name.to_sym
|
103
|
-
|
103
|
+
|
104
104
|
case elements[name]
|
105
105
|
#The most common case: unique child element tags.
|
106
106
|
when NilClass: elements[name] = parse(e)
|
107
|
-
|
107
|
+
|
108
108
|
#Non-unique child elements become arrays:
|
109
|
-
|
109
|
+
|
110
110
|
#We've already created the array: just
|
111
111
|
#add the element.
|
112
112
|
when Array: elements[name] << parse(e)
|
113
|
-
|
113
|
+
|
114
114
|
#We haven't created the array yet: do so,
|
115
115
|
#then put the existing element in, followed
|
116
116
|
#by the new one.
|
@@ -119,17 +119,17 @@ module RForce
|
|
119
119
|
elements[name] << parse(e)
|
120
120
|
end
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
return elements
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
|
127
|
+
|
128
128
|
#Implements the connection to the SalesForce server.
|
129
129
|
class Binding
|
130
130
|
DEFAULT_BATCH_SIZE = 10
|
131
|
-
attr_accessor :batch_size, :url
|
132
|
-
|
131
|
+
attr_accessor :batch_size, :url, :assignment_rule_id, :use_default_rule, :update_mru
|
132
|
+
|
133
133
|
#Fill in the guts of this typical SOAP envelope
|
134
134
|
#with the session ID and the body of the SOAP request.
|
135
135
|
Envelope = <<-HERE
|
@@ -144,60 +144,66 @@ module RForce
|
|
144
144
|
<QueryOptions>
|
145
145
|
<batchSize>%d</batchSize>
|
146
146
|
</QueryOptions>
|
147
|
+
%s
|
147
148
|
</env:Header>
|
148
149
|
<env:Body>
|
149
150
|
%s
|
150
151
|
</env:Body>
|
151
152
|
</env:Envelope>
|
152
153
|
HERE
|
154
|
+
|
155
|
+
AssignmentRuleHeaderUsingRuleId = "<AssignmentRuleHeader><assignment_rule_id>%s</assignment_rule_id></AssignmentRuleHeader>"
|
156
|
+
AssignmentRuleHeaderUsingDefaultRule = "<AssignmentRuleHeader><use_default_rule>true</use_default_rule></AssignmentRuleHeader>"
|
157
|
+
MruHeader = "<MruHeader><update_mru>true</update_mru></MruHeader>"
|
153
158
|
|
154
|
-
|
159
|
+
|
155
160
|
#Connect to the server securely.
|
156
161
|
def initialize(url, sid)
|
157
162
|
init_server(url)
|
158
|
-
|
163
|
+
|
159
164
|
@session_id = sid
|
160
165
|
@batch_size = DEFAULT_BATCH_SIZE
|
161
166
|
end
|
162
|
-
|
163
|
-
|
167
|
+
|
168
|
+
|
164
169
|
def show_debug
|
165
170
|
$DEBUG or ENV['SHOWSOAP']
|
166
171
|
end
|
167
|
-
|
172
|
+
|
168
173
|
|
169
174
|
def init_server(url)
|
170
175
|
@url = URI.parse(url)
|
171
176
|
@server = Net::HTTP.new(@url.host, @url.port)
|
172
177
|
@server.use_ssl = @url.scheme == 'https'
|
173
178
|
@server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
174
|
-
|
175
|
-
# run ruby with -d to see SOAP wiredumps.
|
179
|
+
|
180
|
+
# run ruby with -d or env variable SHOWSOAP=true to see SOAP wiredumps.
|
176
181
|
@server.set_debug_output $stderr if show_debug
|
177
182
|
end
|
178
|
-
|
179
|
-
|
183
|
+
|
184
|
+
|
180
185
|
#Log in to the server and remember the session ID
|
181
186
|
#returned to us by SalesForce.
|
182
187
|
def login(user, password)
|
183
|
-
puts "\n\nIn login(#{user})\n\n"
|
184
|
-
|
185
188
|
@user = user
|
186
189
|
@password = password
|
187
|
-
|
190
|
+
|
188
191
|
response = call_remote(:login, [:username, user, :password, password])
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
+
|
193
|
+
unless response.loginResponse
|
194
|
+
pp response
|
195
|
+
raise "Incorrect user name / password [#{response.fault}]"
|
196
|
+
end
|
197
|
+
|
192
198
|
result = response[:loginResponse][:result]
|
193
199
|
@session_id = result[:sessionId]
|
194
|
-
|
200
|
+
|
195
201
|
init_server(result[:serverUrl])
|
196
|
-
|
202
|
+
|
197
203
|
response
|
198
204
|
end
|
199
205
|
|
200
|
-
|
206
|
+
|
201
207
|
#Call a method on the remote server. Arguments can be
|
202
208
|
#a hash or (if order is important) an array of alternating
|
203
209
|
#keys and values.
|
@@ -206,58 +212,63 @@ module RForce
|
|
206
212
|
expanded = ''
|
207
213
|
@builder = Builder::XmlMarkup.new(:target => expanded)
|
208
214
|
expand({method => args}, 'urn:partner.soap.sforce.com')
|
215
|
+
|
216
|
+
extra_headers = ""
|
217
|
+
extra_headers << (AssignmentRuleHeaderUsingRuleId % assignment_rule_id) if assignment_rule_id
|
218
|
+
extra_headers << AssignmentRuleHeaderUsingDefaultRule if use_default_rule
|
219
|
+
extra_headers << MruHeader if update_mru
|
209
220
|
|
210
221
|
#Fill in the blanks of the SOAP envelope with our
|
211
222
|
#session ID and the expanded XML of our request.
|
212
|
-
request = (Envelope % [@session_id, @batch_size, expanded])
|
213
|
-
|
223
|
+
request = (Envelope % [@session_id, @batch_size, extra_headers, expanded])
|
224
|
+
|
214
225
|
# reset the batch size for the next request
|
215
226
|
@batch_size = DEFAULT_BATCH_SIZE
|
216
|
-
|
227
|
+
|
217
228
|
# gzip request
|
218
229
|
request = encode(request)
|
219
|
-
|
230
|
+
|
220
231
|
headers = {
|
221
232
|
'Connection' => 'Keep-Alive',
|
222
233
|
'Content-Type' => 'text/xml',
|
223
234
|
'SOAPAction' => '""',
|
224
|
-
'User-Agent' => 'ActiveSalesforce
|
235
|
+
'User-Agent' => 'ActiveSalesforce'
|
225
236
|
}
|
226
237
|
|
227
238
|
unless show_debug
|
228
239
|
headers['Accept-Encoding'] = 'gzip'
|
229
240
|
headers['Content-Encoding'] = 'gzip'
|
230
241
|
end
|
231
|
-
|
242
|
+
|
232
243
|
#Send the request to the server and read the response.
|
233
|
-
response = @server.post2(@url.path, request, headers)
|
234
|
-
|
244
|
+
response = @server.post2(@url.path, request.lstrip, headers)
|
245
|
+
|
235
246
|
# decode if we have encoding
|
236
247
|
content = decode(response)
|
237
|
-
|
248
|
+
|
238
249
|
# Check to see if INVALID_SESSION_ID was raised and try to relogin in
|
239
250
|
if method != :login and @session_id and response =~ /<faultcode>sf\:INVALID_SESSION_ID<\/faultcode>/
|
240
251
|
puts "\n\nSession timeout error - auto relogin activated"
|
241
|
-
|
252
|
+
|
242
253
|
login(@user, @password)
|
243
|
-
|
254
|
+
|
244
255
|
#Send the request to the server and read the response.
|
245
256
|
response = @server.post2(@url.path, request, headers)
|
246
|
-
|
257
|
+
|
247
258
|
content = decode(response)
|
248
259
|
end
|
249
|
-
|
260
|
+
|
250
261
|
SoapResponse.new(content)
|
251
262
|
end
|
252
263
|
|
253
|
-
|
264
|
+
|
254
265
|
# decode gzip
|
255
266
|
def decode(response)
|
256
267
|
encoding = response['Content-Encoding']
|
257
|
-
|
268
|
+
|
258
269
|
# return body if no encoding
|
259
270
|
if !encoding then return response.body end
|
260
|
-
|
271
|
+
|
261
272
|
# decode gzip
|
262
273
|
case encoding.strip
|
263
274
|
when 'gzip':
|
@@ -273,7 +284,7 @@ module RForce
|
|
273
284
|
end
|
274
285
|
end
|
275
286
|
|
276
|
-
|
287
|
+
|
277
288
|
# encode gzip
|
278
289
|
def encode(request)
|
279
290
|
return request if show_debug
|
@@ -287,28 +298,28 @@ module RForce
|
|
287
298
|
gzw.close
|
288
299
|
end
|
289
300
|
end
|
290
|
-
|
291
|
-
|
301
|
+
|
302
|
+
|
292
303
|
#Turns method calls on this object into remote SOAP calls.
|
293
304
|
def method_missing(method, *args)
|
294
305
|
unless args.size == 1 && [Hash, Array].include?(args[0].class)
|
295
306
|
raise 'Expected 1 Hash or Array argument'
|
296
307
|
end
|
297
|
-
|
308
|
+
|
298
309
|
call_remote method, args[0]
|
299
310
|
end
|
300
311
|
|
301
|
-
|
312
|
+
|
302
313
|
#Expand Ruby data structures into XML.
|
303
314
|
def expand(args, xmlns = nil)
|
304
315
|
#Nest arrays: [:a, 1, :b, 2] => [[:a, 1], [:b, 2]]
|
305
316
|
if (args.class == Array)
|
306
317
|
args.each_index{|i| args[i, 2] = [args[i, 2]]}
|
307
318
|
end
|
308
|
-
|
319
|
+
|
309
320
|
args.each do |key, value|
|
310
321
|
attributes = xmlns ? {:xmlns => xmlns} : {}
|
311
|
-
|
322
|
+
|
312
323
|
#If the XML tag requires attributes,
|
313
324
|
#the tag name will contain a space
|
314
325
|
#followed by a string representation
|
@@ -318,16 +329,16 @@ module RForce
|
|
318
329
|
#becomes <sObject xsi:type="Opportunity>...</sObject>
|
319
330
|
if key.is_a? String
|
320
331
|
key, modifier = key.split(' ', 2)
|
321
|
-
|
332
|
+
|
322
333
|
attributes.merge!(eval(modifier)) if modifier
|
323
334
|
end
|
324
|
-
|
335
|
+
|
325
336
|
#Create an XML element and fill it with this
|
326
337
|
#value's sub-items.
|
327
338
|
case value
|
328
339
|
when Hash, Array
|
329
340
|
@builder.tag!(key, attributes) do expand value; end
|
330
|
-
|
341
|
+
|
331
342
|
when String
|
332
343
|
@builder.tag!(key, attributes) { @builder.text! value }
|
333
344
|
end
|
data/test/unit/basic_test.rb
CHANGED
@@ -17,10 +17,10 @@
|
|
17
17
|
|
18
18
|
require 'rubygems'
|
19
19
|
|
20
|
-
#require_gem 'activesalesforce', '>= 0.
|
21
|
-
require 'activesalesforce'
|
20
|
+
#require_gem 'activesalesforce', '>= 0.4.3'
|
21
|
+
require File.dirname(__FILE__) + '/../../lib/activesalesforce'
|
22
22
|
|
23
|
-
require 'recorded_test_case'
|
23
|
+
require File.dirname(__FILE__) + '/recorded_test_case'
|
24
24
|
require 'pp'
|
25
25
|
|
26
26
|
|
@@ -30,6 +30,9 @@ end
|
|
30
30
|
class Department < ActiveRecord::Base
|
31
31
|
end
|
32
32
|
|
33
|
+
class Address < ActiveRecord::Base
|
34
|
+
end
|
35
|
+
|
33
36
|
|
34
37
|
module Asf
|
35
38
|
module UnitTests
|
@@ -42,7 +45,7 @@ module Asf
|
|
42
45
|
def initialize(test_method_name)
|
43
46
|
super(test_method_name)
|
44
47
|
|
45
|
-
#force_recording :
|
48
|
+
#force_recording :test_master_detail
|
46
49
|
end
|
47
50
|
|
48
51
|
def setup
|
@@ -51,6 +54,9 @@ module Asf
|
|
51
54
|
super
|
52
55
|
|
53
56
|
@contact = Contact.new
|
57
|
+
|
58
|
+
reset_header_options
|
59
|
+
|
54
60
|
contact.first_name = 'DutchTestFirstName'
|
55
61
|
contact.last_name = 'DutchTestLastName'
|
56
62
|
contact.home_phone = '555-555-1212'
|
@@ -60,10 +66,19 @@ module Asf
|
|
60
66
|
end
|
61
67
|
|
62
68
|
def teardown
|
69
|
+
reset_header_options
|
70
|
+
|
63
71
|
contact.destroy if contact
|
64
72
|
|
65
73
|
super
|
66
74
|
end
|
75
|
+
|
76
|
+
def reset_header_options
|
77
|
+
binding = Contact.connection.binding
|
78
|
+
binding.assignment_rule_id = nil
|
79
|
+
binding.use_default_rule = false
|
80
|
+
binding.update_mru = false
|
81
|
+
end
|
67
82
|
|
68
83
|
|
69
84
|
def test_create_a_contact
|
@@ -101,6 +116,23 @@ module Asf
|
|
101
116
|
user = contact.created_by
|
102
117
|
assert_equal contact.created_by_id, user.id
|
103
118
|
end
|
119
|
+
|
120
|
+
def test_use_update_mru
|
121
|
+
Contact.connection.binding.update_mru = true
|
122
|
+
contact.save
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_use_default_rule
|
126
|
+
Contact.connection.binding.use_default_rule = true
|
127
|
+
contact.save
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_assignment_rule_id
|
131
|
+
Contact.connection.binding.assignment_rule_id = "1234567890"
|
132
|
+
contact.save
|
133
|
+
end
|
134
|
+
|
135
|
+
|
104
136
|
|
105
137
|
def test_add_notes_to_contact
|
106
138
|
n1 = Note.new(:title => "My Title", :body => "My Body")
|
@@ -155,6 +187,10 @@ module Asf
|
|
155
187
|
c1.destroy
|
156
188
|
end
|
157
189
|
end
|
190
|
+
|
191
|
+
def test_find_addresses
|
192
|
+
adresses = Address.find(:all)
|
193
|
+
end
|
158
194
|
|
159
195
|
end
|
160
196
|
|