activesalesforce 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rforce.rb +1 -0
- data/lib/salesforce_connection_adapter.rb +82 -62
- metadata +2 -2
data/lib/rforce.rb
CHANGED
@@ -163,6 +163,7 @@ module RForce
|
|
163
163
|
@url = URI.parse(url)
|
164
164
|
@server = Net::HTTP.new(@url.host, @url.port)
|
165
165
|
@server.use_ssl = @url.scheme == 'https'
|
166
|
+
@server.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
166
167
|
|
167
168
|
# run ruby with -d to see SOAP wiredumps.
|
168
169
|
@server.set_debug_output $stderr if show_debug
|
@@ -73,28 +73,50 @@ module ActiveRecord
|
|
73
73
|
|
74
74
|
@fault = fault
|
75
75
|
|
76
|
-
puts "\nSalesforceError:\n message='#{message}'\n fault='#{fault}'\n\n"
|
76
|
+
#puts "\nSalesforceError:\n message='#{message}'\n fault='#{fault}'\n\n"
|
77
77
|
logger.debug("\nSalesforceError:\n message='#{message}'\n fault='#{fault}'\n\n")
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
+
|
81
82
|
class SalesforceAdapter < AbstractAdapter
|
83
|
+
|
84
|
+
class EntityDefinition
|
85
|
+
attr_reader :name, :columns, :column_name_to_column, :relationships
|
86
|
+
|
87
|
+
def custom?
|
88
|
+
@custom
|
89
|
+
end
|
90
|
+
|
91
|
+
def api_name
|
92
|
+
@custom ? name + "__c" : name
|
93
|
+
end
|
94
|
+
|
95
|
+
def initialize(name, columns, relationships, custom)
|
96
|
+
@name = name
|
97
|
+
@columns = columns
|
98
|
+
@relationships = relationships
|
99
|
+
@custom = custom
|
100
|
+
|
101
|
+
@column_name_to_column = {}
|
102
|
+
@columns.each { |column| @column_name_to_column[column.name] = column }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
82
106
|
COLUMN_NAME_REGEX = /@C_(\w+)/
|
83
107
|
COLUMN_VALUE_REGEX = /@V_'(([^']|\\')*)'/
|
84
108
|
|
85
109
|
include StringHelper
|
86
110
|
|
87
111
|
attr_accessor :batch_size
|
112
|
+
attr_reader :entity_def_map
|
88
113
|
|
89
114
|
def initialize(connection, logger, connection_options, config)
|
90
115
|
super(connection, logger)
|
91
116
|
|
92
117
|
@connection_options, @config = connection_options, config
|
93
118
|
|
94
|
-
@
|
95
|
-
@columns_name_map = {}
|
96
|
-
|
97
|
-
@relationships_map = {}
|
119
|
+
@entity_def_map = {}
|
98
120
|
end
|
99
121
|
|
100
122
|
|
@@ -142,11 +164,18 @@ module ActiveRecord
|
|
142
164
|
# DATABASE STATEMENTS ======================================
|
143
165
|
|
144
166
|
def select_all(sql, name = nil) #:nodoc:
|
145
|
-
|
167
|
+
log(sql, name)
|
168
|
+
|
169
|
+
raw_table_name = sql.match(/FROM (\w+) /)[1]
|
170
|
+
table_name = raw_table_name.singularize
|
146
171
|
entity_name = entity_name_from_table(table_name)
|
172
|
+
entity_def = get_entity_def(entity_name)
|
173
|
+
|
147
174
|
column_names = api_column_names(table_name)
|
148
175
|
|
149
|
-
soql = sql.sub(/SELECT \* FROM
|
176
|
+
soql = sql.sub(/SELECT \* FROM /, "SELECT #{column_names.join(', ')} FROM ")
|
177
|
+
|
178
|
+
soql.sub!(/ FROM \w+ /, " FROM #{entity_def.api_name} ")
|
150
179
|
|
151
180
|
# Look for a LIMIT clause
|
152
181
|
soql.sub!(/LIMIT 1/, "")
|
@@ -161,6 +190,9 @@ module ActiveRecord
|
|
161
190
|
soql = $~.pre_match + column.api_name + $~.post_match
|
162
191
|
end
|
163
192
|
|
193
|
+
# Update table name references
|
194
|
+
soql.sub!(/#{raw_table_name}\./, "#{entity_def.api_name}.")
|
195
|
+
|
164
196
|
# Remove column value prefix
|
165
197
|
soql.gsub!(/@V_/, "")
|
166
198
|
|
@@ -182,14 +214,15 @@ module ActiveRecord
|
|
182
214
|
|
183
215
|
record.each do |name, value|
|
184
216
|
name = column_nameize(name.to_s)
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
217
|
+
if name != "type"
|
218
|
+
# Replace nil element with nil
|
219
|
+
value = nil if value.respond_to?(:xmlattr_nil) and value.xmlattr_nil
|
220
|
+
|
221
|
+
# Ids are returned in an array with 2 duplicate entries...
|
222
|
+
value = value[0] if name == "id"
|
223
|
+
|
224
|
+
row[name] = value
|
225
|
+
end
|
193
226
|
end
|
194
227
|
|
195
228
|
result << row
|
@@ -203,11 +236,13 @@ module ActiveRecord
|
|
203
236
|
self.batch_size = 1
|
204
237
|
|
205
238
|
# Check for SELECT COUNT(*) FROM query
|
206
|
-
matchCount = sql.match(/SELECT COUNT\(\*\) FROM
|
239
|
+
matchCount = sql.match(/SELECT COUNT\(\*\) FROM /)
|
207
240
|
if matchCount
|
208
|
-
sql = "SELECT id FROM #{matchCount
|
241
|
+
sql = "SELECT id FROM #{matchCount.post_match}"
|
209
242
|
end
|
210
243
|
|
244
|
+
log(sql, name)
|
245
|
+
|
211
246
|
result = select_all(sql, name)
|
212
247
|
|
213
248
|
if matchCount
|
@@ -289,7 +324,7 @@ module ActiveRecord
|
|
289
324
|
responseName = (method.to_s + "Response").to_sym
|
290
325
|
finalResponse = response[responseName]
|
291
326
|
|
292
|
-
raise SalesforceError.new(@logger, response[:
|
327
|
+
raise SalesforceError.new(@logger, response[:Fault][:faultstring], response.fault) unless finalResponse
|
293
328
|
|
294
329
|
result = finalResponse[:result]
|
295
330
|
end
|
@@ -306,20 +341,22 @@ module ActiveRecord
|
|
306
341
|
end
|
307
342
|
|
308
343
|
|
309
|
-
def
|
310
|
-
|
311
|
-
|
312
|
-
cached_columns = @columns_map[entity_name]
|
313
|
-
return cached_columns if cached_columns
|
344
|
+
def get_entity_def(entity_name)
|
345
|
+
cached_entity_def = @entity_def_map[entity_name]
|
346
|
+
return cached_entity_def if cached_entity_def
|
314
347
|
|
315
348
|
cached_columns = []
|
316
|
-
@columns_map[entity_name] = cached_columns
|
317
|
-
|
318
349
|
cached_relationships = []
|
319
|
-
@relationships_map[entity_name] = cached_relationships
|
320
|
-
|
321
|
-
metadata = get_result(@connection.describeSObject(:sObjectType => entity_name), :describeSObject)
|
322
350
|
|
351
|
+
begin
|
352
|
+
metadata = get_result(@connection.describeSObject(:sObjectType => entity_name), :describeSObject)
|
353
|
+
custom = false
|
354
|
+
rescue SalesforceError => e
|
355
|
+
# Fallback and see if we can find a custom object with this name
|
356
|
+
metadata = get_result(@connection.describeSObject(:sObjectType => entity_name + "__c"), :describeSObject)
|
357
|
+
custom = true
|
358
|
+
end
|
359
|
+
|
323
360
|
metadata.fields.each do |field|
|
324
361
|
column = SalesforceColumn.new(field)
|
325
362
|
cached_columns << column
|
@@ -340,24 +377,27 @@ module ActiveRecord
|
|
340
377
|
end
|
341
378
|
end
|
342
379
|
end
|
380
|
+
|
381
|
+
entity_def = EntityDefinition.new(entity_name, cached_columns, cached_relationships, custom)
|
382
|
+
@entity_def_map[entity_name] = entity_def
|
343
383
|
|
344
|
-
configure_active_record
|
345
|
-
|
346
|
-
|
384
|
+
configure_active_record entity_def
|
385
|
+
|
386
|
+
entity_def
|
347
387
|
end
|
348
388
|
|
349
389
|
|
350
|
-
def configure_active_record(
|
390
|
+
def configure_active_record(entity_def)
|
391
|
+
entity_name = entity_def.name
|
351
392
|
klass = entity_name.constantize
|
352
|
-
|
353
|
-
klass.pluralize_table_names = false
|
393
|
+
|
354
394
|
klass.set_inheritance_column nil
|
355
395
|
klass.lock_optimistically = false
|
356
396
|
klass.record_timestamps = false
|
357
397
|
klass.default_timezone = :utc
|
358
398
|
|
359
399
|
# Create relationships for any reference field
|
360
|
-
|
400
|
+
entity_def.relationships.each do |relationship|
|
361
401
|
referenceName = relationship.name
|
362
402
|
unless self.respond_to? referenceName.to_sym or relationship.reference_to == "Profile"
|
363
403
|
reference_to = relationship.reference_to
|
@@ -387,32 +427,15 @@ module ActiveRecord
|
|
387
427
|
end
|
388
428
|
|
389
429
|
|
390
|
-
def
|
430
|
+
def columns(table_name, name = nil)
|
391
431
|
entity_name = entity_name_from_table(table_name)
|
392
|
-
|
393
|
-
cached_relationships = @relationships_map[entity_name]
|
394
|
-
|
395
|
-
unless cached_relationships
|
396
|
-
# This will load column and relationship metadata
|
397
|
-
columns(table_name)
|
398
|
-
end
|
399
|
-
|
400
|
-
@relationships_map[entity_name]
|
432
|
+
get_entity_def(entity_name).columns
|
401
433
|
end
|
402
|
-
|
434
|
+
|
403
435
|
|
404
436
|
def columns_map(table_name, name = nil)
|
405
437
|
entity_name = entity_name_from_table(table_name)
|
406
|
-
|
407
|
-
columns_map = @columns_name_map[entity_name]
|
408
|
-
unless columns_map
|
409
|
-
columns_map = {}
|
410
|
-
@columns_name_map[entity_name] = columns_map
|
411
|
-
|
412
|
-
columns(entity_name).each { |column| columns_map[column.name] = column }
|
413
|
-
end
|
414
|
-
|
415
|
-
columns_map
|
438
|
+
get_entity_def(entity_name).column_name_to_column
|
416
439
|
end
|
417
440
|
|
418
441
|
|
@@ -422,7 +445,9 @@ module ActiveRecord
|
|
422
445
|
|
423
446
|
|
424
447
|
def create_sobject(entity_name, id, fields)
|
425
|
-
|
448
|
+
entity_def = get_entity_def(entity_name)
|
449
|
+
|
450
|
+
sobj = [ 'type { :xmlns => "urn:sobject.partner.soap.sforce.com" }', entity_def.api_name ]
|
426
451
|
sobj << 'Id { :xmlns => "urn:sobject.partner.soap.sforce.com" }' << id if id
|
427
452
|
|
428
453
|
# now add any changed fields
|
@@ -435,11 +460,6 @@ module ActiveRecord
|
|
435
460
|
end
|
436
461
|
|
437
462
|
|
438
|
-
def table_name_from_sql(sql)
|
439
|
-
sql.match(/FROM (\w+) /)[1].singularize
|
440
|
-
end
|
441
|
-
|
442
|
-
|
443
463
|
def column_names(table_name)
|
444
464
|
columns(table_name).map { |column| column.name }
|
445
465
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: activesalesforce
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2006-02-
|
6
|
+
version: 0.1.8
|
7
|
+
date: 2006-02-04 00:00:00 -05:00
|
8
8
|
summary: ActiveSalesforce is an extension to the Rails Framework that allows for the dynamic creation and management of ActiveRecord objects through the use of Salesforce meta-data and uses a Salesforce.com organization as the backing store.
|
9
9
|
require_paths:
|
10
10
|
- lib
|