activesalesforce 1.1.3 → 1.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -1
- data/lib/asf_adapter.rb +96 -102
- data/lib/rforce.rb +1 -1
- metadata +1 -1
data/README
CHANGED
data/lib/asf_adapter.rb
CHANGED
@@ -57,8 +57,8 @@ module ActiveRecord
|
|
57
57
|
uri.path = "/services/Soap/u/8.0"
|
58
58
|
url = uri.to_s
|
59
59
|
|
60
|
-
sid = config[:sid]
|
61
|
-
client_id = config[:client_id]
|
60
|
+
sid = config[:sid].to_s
|
61
|
+
client_id = config[:client_id].to_s
|
62
62
|
username = config[:username].to_s
|
63
63
|
password = config[:password].to_s
|
64
64
|
|
@@ -72,6 +72,9 @@ module ActiveRecord
|
|
72
72
|
binding.client_id = client_id if client_id
|
73
73
|
binding.login(username, password) unless sid
|
74
74
|
end
|
75
|
+
|
76
|
+
# Check to insure that the second to last path component is a 'u' for Partner API
|
77
|
+
raise ActiveSalesforce::ASFError.new(logger, "Invalid salesforce server url '#{url}', must be a valid Parter API URL") unless url.match(/\/u\//mi)
|
75
78
|
|
76
79
|
if sid
|
77
80
|
binding = @@cache["sid=#{sid}"] unless binding
|
@@ -83,13 +86,10 @@ module ActiveRecord
|
|
83
86
|
@@cache["sid=#{sid}"] = binding
|
84
87
|
|
85
88
|
debug("Created new connection for [sid='#{sid}']")
|
89
|
+
else
|
90
|
+
debug("Reused existing connection for [sid='#{sid}']")
|
86
91
|
end
|
87
|
-
|
88
|
-
ConnectionAdapters::SalesforceAdapter.new(binding, logger, [url, sid], config)
|
89
92
|
else
|
90
|
-
# Check to insure that the second to last path component is a 'u' for Partner API
|
91
|
-
raise ActiveSalesforce::ASFError.new(logger, "Invalid salesforce server url '#{url}', must be a valid Parter API URL") unless url.match(/\/u\//mi)
|
92
|
-
|
93
93
|
binding = @@cache["#{url}.#{username}.#{password}.#{client_id}"] unless binding
|
94
94
|
|
95
95
|
unless binding
|
@@ -104,9 +104,10 @@ module ActiveRecord
|
|
104
104
|
|
105
105
|
debug("Created new connection for ['#{url}', '#{username}', '#{client_id}'] in #{seconds} seconds")
|
106
106
|
end
|
107
|
-
|
108
|
-
ConnectionAdapters::SalesforceAdapter.new(binding, logger, [url, username, password, sid, client_id], config)
|
109
107
|
end
|
108
|
+
|
109
|
+
ConnectionAdapters::SalesforceAdapter.new(binding, logger, config)
|
110
|
+
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
@@ -121,10 +122,11 @@ module ActiveRecord
|
|
121
122
|
attr_accessor :batch_size
|
122
123
|
attr_reader :entity_def_map, :keyprefix_to_entity_def_map, :config, :class_to_entity_map
|
123
124
|
|
124
|
-
def initialize(connection, logger,
|
125
|
+
def initialize(connection, logger, config)
|
125
126
|
super(connection, logger)
|
126
127
|
|
127
|
-
@connection_options
|
128
|
+
@connection_options = nil
|
129
|
+
@config = config
|
128
130
|
|
129
131
|
@entity_def_map = {}
|
130
132
|
@keyprefix_to_entity_def_map = {}
|
@@ -262,32 +264,31 @@ module ActiveRecord
|
|
262
264
|
# DATABASE STATEMENTS ======================================
|
263
265
|
|
264
266
|
def select_all(sql, name = nil) #:nodoc:
|
265
|
-
|
266
|
-
raw_table_name = sql.match(/FROM (\w+)/mi)[1]
|
267
|
+
raw_table_name = sql.match(/FROM (\w+)/mi)[1]
|
267
268
|
table_name, columns, entity_def = lookup(raw_table_name)
|
268
269
|
|
269
270
|
column_names = columns.map { |column| column.api_name }
|
270
271
|
|
271
272
|
# Check for SELECT COUNT(*) FROM query
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
end
|
273
|
+
|
274
|
+
# Rails 1.1
|
275
|
+
selectCountMatch = sql.match(/SELECT\s+COUNT\(\*\)\s+AS\s+count_all\s+FROM/mi)
|
276
|
+
|
277
|
+
# Rails 1.0
|
278
|
+
selectCountMatch = sql.match(/SELECT\s+COUNT\(\*\)\s+FROM/mi) unless selectCountMatch
|
279
|
+
|
280
|
+
if selectCountMatch
|
281
|
+
soql = "SELECT COUNT() FROM#{selectCountMatch.post_match}"
|
282
|
+
else
|
283
|
+
if sql.match(/SELECT\s+\*\s+FROM/mi)
|
284
|
+
# Always convert SELECT * to select all columns (required for the AR attributes mechanism to work correctly)
|
285
|
+
soql = sql.sub(/SELECT .+ FROM/mi, "SELECT #{column_names.join(', ')} FROM")
|
286
|
+
else
|
287
|
+
soql = sql
|
288
288
|
end
|
289
|
-
|
290
|
-
|
289
|
+
end
|
290
|
+
|
291
|
+
soql.sub!(/\s+FROM\s+\w+/mi, " FROM #{entity_def.api_name}")
|
291
292
|
|
292
293
|
if selectCountMatch
|
293
294
|
query_result = get_result(@connection.query(:queryString => soql), :query)
|
@@ -295,26 +296,26 @@ module ActiveRecord
|
|
295
296
|
end
|
296
297
|
|
297
298
|
# Look for a LIMIT clause
|
298
|
-
|
299
|
-
|
299
|
+
limit = extract_sql_modifier(soql, "LIMIT")
|
300
|
+
limit = MAX_BOXCAR_SIZE unless limit
|
301
|
+
|
302
|
+
# Look for an OFFSET clause
|
303
|
+
offset = extract_sql_modifier(soql, "OFFSET")
|
304
|
+
|
305
|
+
# Fixup column references to use api names
|
306
|
+
columns = entity_def.column_name_to_column
|
307
|
+
soql.gsub!(/((?:\w+\.)?\w+)(?=\s*(?:=|!=|<|>|<=|>=|like)\s*(?:'[^']*'|NULL|TRUE|FALSE))/mi) do |column_name|
|
308
|
+
# strip away any table alias
|
309
|
+
column_name.sub!(/\w+\./, '')
|
300
310
|
|
301
|
-
|
302
|
-
|
311
|
+
column = columns[column_name]
|
312
|
+
raise ActiveSalesforce::ASFError.new(@logger, "Column not found for #{column_name}!") unless column
|
303
313
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
column = columns[column_name]
|
311
|
-
raise ActiveSalesforce::ASFError.new(@logger, "Column not found for #{column_name}!") unless column
|
312
|
-
|
313
|
-
column.api_name
|
314
|
-
end
|
315
|
-
|
316
|
-
# Update table name references
|
317
|
-
soql.sub!(/#{raw_table_name}\./mi, "#{entity_def.api_name}.")
|
314
|
+
column.api_name
|
315
|
+
end
|
316
|
+
|
317
|
+
# Update table name references
|
318
|
+
soql.sub!(/#{raw_table_name}\./mi, "#{entity_def.api_name}.")
|
318
319
|
|
319
320
|
@connection.batch_size = @batch_size if @batch_size
|
320
321
|
@batch_size = nil
|
@@ -326,15 +327,14 @@ module ActiveRecord
|
|
326
327
|
add_rows(entity_def, query_result, result, limit)
|
327
328
|
|
328
329
|
while ((query_result[:done].casecmp("true") != 0) and (result.size < limit or limit == 0))
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
add_rows(entity_def, query_result, result, limit)
|
334
|
-
end
|
330
|
+
# Now queryMore
|
331
|
+
locator = query_result[:queryLocator];
|
332
|
+
query_result = get_result(@connection.queryMore(:queryLocator => locator), :queryMore)
|
335
333
|
|
336
|
-
result
|
337
|
-
|
334
|
+
add_rows(entity_def, query_result, result, limit)
|
335
|
+
end
|
336
|
+
|
337
|
+
result
|
338
338
|
end
|
339
339
|
|
340
340
|
def add_rows(entity_def, query_result, result, limit)
|
@@ -605,52 +605,50 @@ module ActiveRecord
|
|
605
605
|
return cached_entity_def
|
606
606
|
end
|
607
607
|
|
608
|
-
|
609
|
-
|
610
|
-
|
608
|
+
cached_columns = []
|
609
|
+
cached_relationships = []
|
610
|
+
|
611
|
+
begin
|
612
|
+
metadata = get_result(@connection.describeSObject(:sObjectType => entity_name), :describeSObject)
|
613
|
+
custom = false
|
614
|
+
rescue ActiveSalesforce::ASFError => e
|
615
|
+
# Fallback and see if we can find a custom object with this name
|
616
|
+
debug(" Unable to find medata for '#{entity_name}', falling back to custom object name #{entity_name + "__c"}")
|
611
617
|
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
metadata = get_result(@connection.describeSObject(:sObjectType => entity_name + "__c"), :describeSObject)
|
620
|
-
custom = true
|
621
|
-
end
|
618
|
+
metadata = get_result(@connection.describeSObject(:sObjectType => entity_name + "__c"), :describeSObject)
|
619
|
+
custom = true
|
620
|
+
end
|
621
|
+
|
622
|
+
metadata[:fields].each do |field|
|
623
|
+
column = SalesforceColumn.new(field)
|
624
|
+
cached_columns << column
|
622
625
|
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
626
|
+
cached_relationships << SalesforceRelationship.new(field, column) if field[:type] =~ /reference/mi
|
627
|
+
end
|
628
|
+
|
629
|
+
relationships = metadata[:childRelationships]
|
630
|
+
if relationships
|
631
|
+
relationships = [ relationships ] unless relationships.is_a? Array
|
629
632
|
|
630
|
-
relationships
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
relationships.each do |relationship|
|
635
|
-
if relationship[:cascadeDelete] == "true"
|
636
|
-
r = SalesforceRelationship.new(relationship)
|
637
|
-
cached_relationships << r
|
638
|
-
end
|
633
|
+
relationships.each do |relationship|
|
634
|
+
if relationship[:cascadeDelete] == "true"
|
635
|
+
r = SalesforceRelationship.new(relationship)
|
636
|
+
cached_relationships << r
|
639
637
|
end
|
640
638
|
end
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
639
|
+
end
|
640
|
+
|
641
|
+
key_prefix = metadata[:keyPrefix]
|
642
|
+
|
643
|
+
entity_def = ActiveSalesforce::EntityDefinition.new(self, entity_name, entity_klass,
|
644
|
+
cached_columns, cached_relationships, custom, key_prefix)
|
645
|
+
|
646
|
+
@entity_def_map[entity_name] = entity_def
|
647
|
+
@keyprefix_to_entity_def_map[key_prefix] = entity_def
|
648
|
+
|
649
|
+
configure_active_record(entity_def)
|
650
|
+
|
651
|
+
entity_def
|
654
652
|
end
|
655
653
|
|
656
654
|
|
@@ -690,10 +688,6 @@ module ActiveRecord
|
|
690
688
|
|
691
689
|
begin
|
692
690
|
referenced_klass = class_from_entity_name(reference_to)
|
693
|
-
|
694
|
-
# Verify that we found an ActiveRecord descendant that uses the SalesforceAdapter
|
695
|
-
referenced_klass = nil unless referenced_klass.connection.is_a?(SalesforceAdapter)
|
696
|
-
|
697
691
|
rescue NameError => e
|
698
692
|
# Automatically create a least a stub for the referenced entity
|
699
693
|
debug(" Creating ActiveRecord stub for the referenced entity '#{reference_to}'")
|
data/lib/rforce.rb
CHANGED
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: activesalesforce
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.1.
|
6
|
+
version: 1.1.4
|
7
7
|
date: 2007-03-28 00:00:00 -04:00
|
8
8
|
summary: ActiveSalesforce (ASF) is a Rails connection adapter that provides direct access to Salesforce.com hosted data and metadata via the ActiveRecord model layer. Objects, fields, and relationships are all auto surfaced as active record attributes and rels.
|
9
9
|
require_paths:
|