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 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
- @columns_map = {}
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
- table_name = table_name_from_sql(sql)
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 \w+ /, "SELECT #{column_names.join(', ')} FROM #{table_name} ")
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
- # Replace nil element with nil
187
- value = nil if value.respond_to?(:xmlattr_nil) and value.xmlattr_nil
188
-
189
- # Ids are returned in an array with 2 duplicate entries...
190
- value = value[0] if name == "id"
191
-
192
- row[name] = value
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 (\w+)/)
239
+ matchCount = sql.match(/SELECT COUNT\(\*\) FROM /)
207
240
  if matchCount
208
- sql = "SELECT id FROM #{matchCount[1].singularize} #{matchCount.post_match}"
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[:fault][:faultstring], response.fault) unless finalResponse
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 columns(table_name, name = nil)
310
- entity_name = entity_name_from_table(table_name)
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 entity_name
345
-
346
- cached_columns
384
+ configure_active_record entity_def
385
+
386
+ entity_def
347
387
  end
348
388
 
349
389
 
350
- def configure_active_record(entity_name)
390
+ def configure_active_record(entity_def)
391
+ entity_name = entity_def.name
351
392
  klass = entity_name.constantize
352
- klass.table_name = entity_name
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
- @relationships_map[entity_name].each do |relationship|
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 relationships(table_name)
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
- sobj = [ 'type { :xmlns => "urn:sobject.partner.soap.sforce.com" }', entity_name ]
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
7
- date: 2006-02-03 00:00:00 -05:00
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