copious-activerecord-activesalesforce-adapter 2.2.2

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.
Files changed (33) hide show
  1. data/README +51 -0
  2. data/lib/active_record/connection_adapters/activesalesforce.rb +36 -0
  3. data/lib/active_record/connection_adapters/activesalesforce_adapter.rb +784 -0
  4. data/lib/active_record/connection_adapters/asf_active_record.rb +40 -0
  5. data/lib/active_record/connection_adapters/boxcar_command.rb +66 -0
  6. data/lib/active_record/connection_adapters/column_definition.rb +95 -0
  7. data/lib/active_record/connection_adapters/entity_definition.rb +59 -0
  8. data/lib/active_record/connection_adapters/id_resolver.rb +84 -0
  9. data/lib/active_record/connection_adapters/recording_binding.rb +90 -0
  10. data/lib/active_record/connection_adapters/relationship_definition.rb +81 -0
  11. data/lib/active_record/connection_adapters/result_array.rb +31 -0
  12. data/lib/active_record/connection_adapters/rforce.rb +361 -0
  13. data/lib/active_record/connection_adapters/sid_authentication_filter.rb +57 -0
  14. data/test/unit/basic_test.rb +203 -0
  15. data/test/unit/config.yml +5 -0
  16. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_add_notes_to_contact.recording +1966 -0
  17. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_assignment_rule_id.recording +1621 -0
  18. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_batch_insert.recording +1611 -0
  19. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_client_id.recording +1618 -0
  20. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_count_contacts.recording +1620 -0
  21. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_create_a_contact.recording +1611 -0
  22. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_a_contact.recording +1611 -0
  23. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_a_contact_by_first_name.recording +3468 -0
  24. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_a_contact_by_id.recording +1664 -0
  25. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_find_addresses.recording +1635 -0
  26. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_get_created_by_from_contact.recording +4307 -0
  27. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_master_detail.recording +1951 -0
  28. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_read_all_content_columns.recording +1611 -0
  29. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_save_a_contact.recording +1611 -0
  30. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_use_default_rule.recording +1618 -0
  31. data/test/unit/recorded_results/AsfUnitTestsBasicTest.test_use_update_mru.recording +1618 -0
  32. data/test/unit/recorded_test_case.rb +83 -0
  33. metadata +108 -0
@@ -0,0 +1,40 @@
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
+ module ActiveSalesforce
19
+
20
+ module ActiveRecord
21
+
22
+ module Mixin
23
+ def self.append_features(base) #:nodoc:
24
+ super
25
+
26
+ base.class_eval do
27
+ class << self
28
+ def set_table_name(value = nil, &block)
29
+ super(value, &block)
30
+
31
+ connection.set_class_for_entity(self, table_name.singularize)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,66 @@
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 'pp'
19
+
20
+
21
+ module ActiveSalesforce
22
+ module BoxcarCommand
23
+
24
+ class Base
25
+ attr_reader :verb, :args
26
+
27
+ def initialize(connection, verb, args)
28
+ @connection = connection
29
+ @verb = verb
30
+ @args = args
31
+ end
32
+
33
+ def after_execute(result)
34
+ end
35
+ end
36
+
37
+
38
+ class Insert < Base
39
+ def initialize(connection, sobject, idproxy)
40
+ super(connection, :create, sobject)
41
+ @idproxy = idproxy
42
+ end
43
+
44
+ def after_execute(result)
45
+ id = result[:id]
46
+ @idproxy << id if id
47
+ end
48
+ end
49
+
50
+
51
+ class Update < Base
52
+ def initialize(connection, sobject)
53
+ super(connection, :update, sobject)
54
+ end
55
+ end
56
+
57
+
58
+ class Delete < Base
59
+ def initialize(connection, ids)
60
+ super(connection, :delete, ids)
61
+ end
62
+ end
63
+
64
+
65
+ end
66
+ end
@@ -0,0 +1,95 @@
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 'pp'
19
+ require 'active_record/connection_adapters/abstract_adapter'
20
+
21
+
22
+ module ActiveRecord
23
+ module StringHelper
24
+ def column_nameize(s)
25
+ s.underscore
26
+ end
27
+ end
28
+
29
+ module ConnectionAdapters
30
+ class SalesforceColumn < Column
31
+ include StringHelper
32
+
33
+ attr_reader :api_name, :custom, :label, :createable, :updateable, :reference_to
34
+
35
+ def initialize(field)
36
+ @api_name = field[:name]
37
+ @custom = field[:custom] == "true"
38
+ @name = column_nameize(@api_name)
39
+ @type = get_type(field[:type])
40
+ @limit = field[:length]
41
+ @label = field[:label]
42
+ @name_field = field[:nameField] == "true"
43
+
44
+ @text = [:string, :text].include? @type
45
+ @number = [:float, :integer].include? @type
46
+
47
+ @createable = field[:createable] == "true"
48
+ @updateable = field[:updateable] == "true"
49
+
50
+ if field[:type] =~ /reference/i
51
+ @reference_to = field[:referenceTo]
52
+ @one_to_many = false
53
+ @cascade_delete = false
54
+
55
+ @name = @name.chop.chop << "id__c" if @custom
56
+ end
57
+ end
58
+
59
+ def is_name?
60
+ @name_field
61
+ end
62
+
63
+ def get_type(field_type)
64
+ case field_type
65
+ when /int/i
66
+ :integer
67
+ when /currency|percent/i
68
+ :float
69
+ when /datetime/i
70
+ :datetime
71
+ when /date/i
72
+ :date
73
+ when /id|string|textarea/i
74
+ :text
75
+ when /phone|fax|email|url/i
76
+ :string
77
+ when /blob|binary/i
78
+ :binary
79
+ when /boolean/i
80
+ :boolean
81
+ when /picklist/i
82
+ :text
83
+ when /reference/i
84
+ :text
85
+ end
86
+ end
87
+
88
+ def human_name
89
+ @label
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,59 @@
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 'pp'
19
+
20
+
21
+ module ActiveSalesforce
22
+ class EntityDefinition
23
+ attr_reader :name, :asf_class, :columns, :column_name_to_column, :api_name_to_column, :relationships, :key_prefix
24
+
25
+ def initialize(connection, name, asf_class, columns, relationships, custom, key_prefix)
26
+ @connection = connection
27
+ @name = name
28
+ @asf_class = asf_class
29
+ @columns = columns
30
+ @relationships = relationships
31
+ @custom = custom
32
+ @key_prefix = key_prefix
33
+
34
+ @column_name_to_column = {}
35
+ @columns.each { |column| @column_name_to_column[column.name] = column }
36
+
37
+ @api_name_to_column = {}
38
+ @columns.each { |column| @api_name_to_column[column.api_name] = column }
39
+ end
40
+
41
+ def custom?
42
+ @custom
43
+ end
44
+
45
+ def api_name
46
+ @custom ? name + "__c" : name
47
+ end
48
+
49
+ def layouts
50
+ return @layouts if @layouts
51
+
52
+ # Lazy load Layout information
53
+ response = @connection.binding.describeLayout(:sObjectType => api_name)
54
+ @layouts = @connection.get_result(response, :describeLayout)
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -0,0 +1,84 @@
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 'pp'
19
+
20
+
21
+ module ActiveSalesforce
22
+ class IdResolver
23
+ attr_reader :object_type_to_ids
24
+
25
+ def initialize(connection)
26
+ @connection = connection
27
+ @object_type_to_ids = {}
28
+ end
29
+
30
+
31
+ def add(record, columns = nil)
32
+ if columns
33
+ columns = columns.to_a.map { |column_name| record.column_for_attribute(column_name) }
34
+ else
35
+ columns = record.class.columns
36
+ end
37
+
38
+ columns.each do |column|
39
+ reference_to = column.reference_to
40
+ next unless reference_to
41
+
42
+ value = record.send(column.name)
43
+ if value
44
+ ids = @object_type_to_ids[reference_to] ||= Set.new
45
+ ids << value
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ def resolve
52
+ result = {}
53
+
54
+ @object_type_to_ids.each do |object_type, ids|
55
+ entity_def = @connection.get_entity_def(object_type)
56
+
57
+ fields = (entity_def.columns.reject { |column| not column.is_name? }).map { |column| column.api_name }
58
+
59
+ # DCHASMAN TODO Boxcar into requests of no more than 200 retrieves per request
60
+ puts "Resolving references to #{object_type}"
61
+ field_values = @connection.retrieve_field_values(object_type, fields, ids.to_a, "#{self}.resolve()")
62
+
63
+ field_values.each do |field_value|
64
+ id = field_value.delete(:Id)
65
+ result[id] = field_value
66
+ end
67
+ end
68
+
69
+ result
70
+ end
71
+
72
+
73
+ def serialize
74
+ YAML.dump @object_type_to_ids
75
+ end
76
+
77
+
78
+ def deserialize(source)
79
+ @object_type_to_ids = YAML.load(source)
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,90 @@
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 'yaml'
19
+
20
+
21
+ module ActiveSalesforce
22
+
23
+ class ASFError < RuntimeError
24
+ attr :fault
25
+
26
+ def initialize(logger, message, fault = nil)
27
+ super message
28
+
29
+ @fault = fault
30
+
31
+ logger.debug("\nASFError:\n message='#{message}'\n fault='#{fault}'\n\n")
32
+ end
33
+ end
34
+
35
+
36
+ class ASFRecordingBindingError < ASFError
37
+ def initialize(logger, message)
38
+ super(logger, message)
39
+ end
40
+ end
41
+
42
+
43
+ class RecordingBinding < RForce::Binding
44
+
45
+ attr_reader :recorded_responses
46
+
47
+ def initialize(url, sid, recording, recording_source, logger)
48
+ super(url, sid)
49
+
50
+ @recording = recording
51
+ @recorded_responses = {}
52
+ @recording_source = recording_source
53
+ @logger = logger
54
+
55
+ unless @recording
56
+ YAML.load_documents(recording_source) do |recorded_response|
57
+ @recorded_responses.merge!(recorded_response)
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ #Call a method on the remote server. Arguments can be
64
+ #a hash or (if order is important) an array of alternating
65
+ #keys and values.
66
+ def call_remote(method, args)
67
+ # Blank out username and password
68
+ safe_args = args.inject([]) {|memo, v| memo << ((memo.last == :username or memo.last == :password) ? "" : v) }
69
+ key = "#{method}(#{safe_args.join(':')})"
70
+
71
+ if @recording
72
+ response = super(method, args)
73
+
74
+ unless @recorded_responses[key]
75
+ # track this { key => request } to avoid duplication in the YAML
76
+ @recorded_responses[key] = true
77
+
78
+ YAML.dump({ key, response }, @recording_source)
79
+ end
80
+ else
81
+ response = @recorded_responses[key]
82
+ raise ASFRecordingBindingError.new(@logger, "Unable to find matching response for recorded request '#{key}'") unless response
83
+ end
84
+
85
+ response
86
+ end
87
+
88
+ end
89
+
90
+ end
@@ -0,0 +1,81 @@
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 'pp'
19
+
20
+
21
+ module ActiveRecord
22
+ module StringHelper
23
+ def column_nameize(s)
24
+ s.underscore
25
+ end
26
+ end
27
+
28
+ module ConnectionAdapters
29
+
30
+ class SalesforceRelationship
31
+ include StringHelper
32
+
33
+ attr_reader :name, :api_name, :custom, :foreign_key, :label, :reference_to, :one_to_many
34
+
35
+ def initialize(source, column = nil)
36
+ if source[:childSObject]
37
+ relationship = source
38
+
39
+ if relationship[:relationshipName]
40
+ @api_name = relationship[:relationshipName]
41
+ @one_to_many = true
42
+ @label = @api_name
43
+ @name = column_nameize(@api_name)
44
+ @custom = false
45
+ else
46
+ @api_name = relationship[:field]
47
+ @one_to_many = relationship[:cascadeDelete] == "true"
48
+ @label = relationship[:childSObject].pluralize
49
+ @custom = relationship[:childSObject].match(/__c$/)
50
+
51
+ name = relationship[:childSObject]
52
+ name = name.chop.chop.chop if custom
53
+
54
+ @name = column_nameize(name.pluralize)
55
+ @name = @name + "__c" if custom
56
+ end
57
+
58
+ @reference_to = relationship[:childSObject]
59
+
60
+ @foreign_key = column_nameize(relationship[:field])
61
+ @foreign_key = @foreign_key.chop.chop << "id__c" if @foreign_key.match(/__c$/)
62
+ else
63
+ field = source
64
+
65
+ @api_name = field[:name]
66
+ @custom = field[:custom] == "true"
67
+
68
+ @api_name = @api_name.chop.chop unless @custom
69
+
70
+ @label = field[:label]
71
+ @reference_to = field[:referenceTo]
72
+ @one_to_many = false
73
+
74
+ @foreign_key = column.name
75
+ @name = column_nameize(@api_name)
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,31 @@
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 'pp'
19
+
20
+
21
+ module ActiveSalesforce
22
+
23
+ class ResultArray < Array
24
+ attr_reader :actual_size
25
+
26
+ def initialize(actual_size)
27
+ @actual_size = actual_size
28
+ end
29
+ end
30
+
31
+ end