salesforce_ar_sync 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +28 -0
- data/app/controllers/salesforce_ar_sync/soap_message_controller.rb +3 -1
- data/lib/generators/salesforce_ar_sync/configuration/templates/salesforce_ar_sync.yml +6 -3
- data/lib/salesforce_ar_sync/engine.rb +3 -1
- data/lib/salesforce_ar_sync/extenders/salesforce_syncable.rb +1 -0
- data/lib/salesforce_ar_sync/salesforce_sync.rb +7 -4
- data/lib/salesforce_ar_sync/soap_handler/base.rb +11 -5
- data/lib/salesforce_ar_sync/soap_handler/delete.rb +16 -14
- data/lib/salesforce_ar_sync/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f37d587db2ecda95601160de49a915cff74ca31a
|
4
|
+
data.tar.gz: e3451ccede1bcbe1a1ac6e59aa39241a0862f5cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2fb081124bed9670b20b5485136dd1adbfedc7fd6b28db5438d1ddf0c1c11a04c96cb8a9f6dbf72b665c8f76b3c2fc853d1f57064840bd23c9d36babe44a8703
|
7
|
+
data.tar.gz: 6a3edd80c362394d93906a2888d8b9fb54fe4023c81c3a58dcb38efc3aac2edf094dfd9c3877178c71cb360875f1868224c1e23cca6d83acf82f82096914266f
|
data/README.md
CHANGED
@@ -111,6 +111,7 @@ The options available to configure are
|
|
111
111
|
* __organization_id__: the 18 character organization id of your Salesforce instance
|
112
112
|
* __sync_enabled__: a global sync enabled flag which is a boolean true/false
|
113
113
|
* __namespace_prefix__: Namespace prefix of your Salesforce app in case you specified one
|
114
|
+
* __deletion_map__: Salesforce object names mapped to internal app name.
|
114
115
|
|
115
116
|
To generate a YAML file
|
116
117
|
|
@@ -125,6 +126,7 @@ which will create a template salesforce_ar_sync.yml in /config that looks like t
|
|
125
126
|
organization_id: <organization id> #18 character organization_id
|
126
127
|
sync_enabled: true
|
127
128
|
namespace_prefix:
|
129
|
+
deletion_map:
|
128
130
|
|
129
131
|
|
130
132
|
To use the ENV variable you must pass environemnt variables to rails via the _export_ command in bash or before the
|
@@ -134,6 +136,12 @@ initializer loads the ENV settings.
|
|
134
136
|
$ export SALESFORCE_AR_SYNC_SYNC_ENABLED=true
|
135
137
|
$ export SALESFORCE_AR_NAMESPACE_PREFIX=my_prefix
|
136
138
|
|
139
|
+
An example of adding an aliased object to the deletion map should look like the following:
|
140
|
+
|
141
|
+
deletion_map:
|
142
|
+
-
|
143
|
+
Account: 'YourModelName'
|
144
|
+
|
137
145
|
### Model Options
|
138
146
|
The model can have several options set:
|
139
147
|
|
@@ -159,6 +167,8 @@ The model can have several options set:
|
|
159
167
|
|
160
168
|
[__except__](#except)
|
161
169
|
|
170
|
+
[__unscoped_updates__](#unscoped_updates)
|
171
|
+
|
162
172
|
#### <a id="salesforce_sync_enabled"></a>salesforce_sync_enabled
|
163
173
|
Model level option to enable disable the sync, defaults to true.
|
164
174
|
|
@@ -246,6 +256,14 @@ method is given then only the salesforce_skip_sync attribute is used. Defaults t
|
|
246
256
|
:except => :except_method_name
|
247
257
|
````
|
248
258
|
|
259
|
+
#### unscoped_updates
|
260
|
+
Enable bypassing the default scope when searching for records to update. This is useful when using a
|
261
|
+
soft deletion strategy that can respect SF undeletion.
|
262
|
+
|
263
|
+
````ruby
|
264
|
+
:unscoped_updates => true
|
265
|
+
````
|
266
|
+
|
249
267
|
### Stopping the Sync
|
250
268
|
|
251
269
|
Stopping the gem from syncing can be done on three levels.
|
@@ -430,6 +448,16 @@ This is done using the :sync_outbound_delete option, which can take either a boo
|
|
430
448
|
end
|
431
449
|
```
|
432
450
|
|
451
|
+
### Soft Deletes
|
452
|
+
Setting unscoped_updates to true will permit you to find deleted objects to sync changes to. You can implement virtual attributes matching the
|
453
|
+
undelete field in SF to implement the soft deletion strategy of your choosing. For the paranoia gem:
|
454
|
+
|
455
|
+
```ruby
|
456
|
+
def undeleted=(value)
|
457
|
+
restore if value
|
458
|
+
end
|
459
|
+
```
|
460
|
+
|
433
461
|
## Errors
|
434
462
|
|
435
463
|
### Outbound Message Errors
|
@@ -4,17 +4,20 @@ production:
|
|
4
4
|
# Salesforce owned IPs from: https://help.salesforce.com/apex/HTViewSolution?language=en_US&id=000003652
|
5
5
|
ip_ranges: "204.14.232.0/23,204.14.237.0/24,96.43.144.0/22,96.43.148.0/22,204.14.234.0/23,204.14.238.0/23,182.50.76.0/22"
|
6
6
|
namespace_prefix:
|
7
|
-
|
7
|
+
deletion_map:
|
8
|
+
|
8
9
|
development:
|
9
10
|
organization_id: <%= @organization_id %>
|
10
11
|
sync_enabled: false
|
11
12
|
# Salesforce owned IPs from: https://help.salesforce.com/apex/HTViewSolution?language=en_US&id=000003652
|
12
13
|
ip_ranges: "204.14.232.0/23,204.14.237.0/24,96.43.144.0/22,96.43.148.0/22,204.14.234.0/23,204.14.238.0/23,182.50.76.0/22"
|
13
14
|
namespace_prefix:
|
14
|
-
|
15
|
+
deletion_map:
|
16
|
+
|
15
17
|
test:
|
16
18
|
organization_id: <%= @organization_id %>
|
17
19
|
sync_enabled: false
|
18
20
|
# Salesforce owned IPs from: https://help.salesforce.com/apex/HTViewSolution?language=en_US&id=000003652
|
19
21
|
ip_ranges: "204.14.232.0/23,204.14.237.0/24,96.43.144.0/22,96.43.148.0/22,204.14.234.0/23,204.14.238.0/23,182.50.76.0/22"
|
20
|
-
namespace_prefix:
|
22
|
+
namespace_prefix:
|
23
|
+
deletion_map:
|
@@ -3,7 +3,7 @@ module SalesforceArSync
|
|
3
3
|
initializer "salesforce_ar_sync.load_app_instance_data" do |app|
|
4
4
|
SalesforceArSync.setup do |config|
|
5
5
|
config.app_root = app.root
|
6
|
-
|
6
|
+
|
7
7
|
#Load the configuration from the environment or a yaml file or disable it if no config present
|
8
8
|
SalesforceArSync.config = Hash.new
|
9
9
|
#load the config file if we have it
|
@@ -13,6 +13,7 @@ module SalesforceArSync
|
|
13
13
|
SalesforceArSync.config["SYNC_ENABLED"] = config['sync_enabled']
|
14
14
|
SalesforceArSync.config["IP_RANGES"] = config['ip_ranges'].split(',').map{ |ip| ip.strip }
|
15
15
|
SalesforceArSync.config["NAMESPACE_PREFIX"] = config['namespace_prefix']
|
16
|
+
SalesforceArSync.config['DELETION_MAP'] = config['deletion_map'].stringify_keys
|
16
17
|
end
|
17
18
|
|
18
19
|
#if we have ENV flags prefer them
|
@@ -20,6 +21,7 @@ module SalesforceArSync
|
|
20
21
|
SalesforceArSync.config["SYNC_ENABLED"] = ENV["SALESFORCE_AR_SYNC_SYNC_ENABLED"] if ENV.include? "SALESFORCE_AR_SYNC_SYNC_ENABLED"
|
21
22
|
SalesforceArSync.config["IP_RANGES"] = ENV["SALESFORCE_AR_SYNC_IP_RANGES"].split(',').map{ |ip| ip.strip } if ENV["SALESFORCE_AR_SYNC_IP_RANGES"]
|
22
23
|
SalesforceArSync.config["NAMESPACE_PREFIX"] = ENV["SALESFORCE_AR_NAMESPACE_PREFIX"] if ENV["SALESFORCE_AR_NAMESPACE_PREFIX"]
|
24
|
+
SalesforceArSync.config['DELETION_MAP'] = ENV['DELETION_MAP'] if ENV['DELETION_MAP']
|
23
25
|
|
24
26
|
#do we have valid config options now?
|
25
27
|
if !SalesforceArSync.config["ORGANIZATION_ID"].present? || SalesforceArSync.config["ORGANIZATION_ID"].length != 18
|
@@ -17,6 +17,7 @@ module SalesforceArSync
|
|
17
17
|
|
18
18
|
self.sync_inbound_delete = options.has_key?(:sync_inbound_delete) ? options[:sync_inbound_delete] : true
|
19
19
|
self.sync_outbound_delete = options.has_key?(:sync_outbound_delete) ? options[:sync_outbound_delete] : false
|
20
|
+
self.unscoped_updates = options.has_key?(:unscoped_updates) ? options[:unscoped_updates] : false
|
20
21
|
|
21
22
|
self.salesforce_object_name_method = options.has_key?(:salesforce_object_name) ? options[:salesforce_object_name] : nil
|
22
23
|
self.salesforce_skip_sync_method = options.has_key?(:except) ? options[:except] : nil
|
@@ -39,6 +39,9 @@ module SalesforceArSync
|
|
39
39
|
attr_accessor :sync_inbound_delete
|
40
40
|
attr_accessor :sync_outbound_delete
|
41
41
|
|
42
|
+
# Specify whether we should use an unscoped find to update an object (useful with paranoia gem to handle undeletes)
|
43
|
+
attr_accessor :unscoped_updates
|
44
|
+
|
42
45
|
attr_accessor :salesforce_web_id_attribute_name
|
43
46
|
attr_accessor :salesforce_sync_web_id
|
44
47
|
attr_accessor :activerecord_web_id_attribute_name
|
@@ -56,12 +59,12 @@ module SalesforceArSync
|
|
56
59
|
# Lastly it will create a new record setting it's salesforce_id
|
57
60
|
def salesforce_update(attributes={})
|
58
61
|
raise ArgumentError, "#{salesforce_id_attribute_name} parameter required" if attributes[salesforce_id_attribute_name].blank?
|
59
|
-
|
60
|
-
object =
|
61
|
-
object ||=
|
62
|
+
data_source = unscoped_updates ? unscoped : self
|
63
|
+
object = data_source.find_by(salesforce_id: attributes[salesforce_id_attribute_name])
|
64
|
+
object ||= data_source.find_by(activerecord_web_id_attribute_name => attributes[salesforce_web_id_attribute_name]) if salesforce_sync_web_id? && attributes[salesforce_web_id_attribute_name]
|
62
65
|
|
63
66
|
if object.nil?
|
64
|
-
object =
|
67
|
+
object = new
|
65
68
|
salesforce_default_attributes_for_create.merge(:salesforce_id => attributes[salesforce_id_attribute_name]).each_pair do |k, v|
|
66
69
|
object.send("#{k}=", v)
|
67
70
|
end
|
@@ -34,9 +34,9 @@ module SalesforceArSync
|
|
34
34
|
|
35
35
|
#xml for SFDC response
|
36
36
|
#called from soap_message_controller
|
37
|
-
def generate_response(error = nil)
|
37
|
+
def generate_response(error = nil)
|
38
38
|
response = "<Ack>#{sobjects.nil? ? false : true}</Ack>" unless error
|
39
|
-
if error
|
39
|
+
if error
|
40
40
|
response = "<soapenv:Fault><faultcode>soap:Receiver</faultcode><faultstring>#{error.message}</faultstring></soapenv:Fault>"
|
41
41
|
end
|
42
42
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soapenv:Body><notificationsResponse>#{response}</notificationsResponse></soapenv:Body></soapenv:Envelope>"
|
@@ -45,11 +45,17 @@ module SalesforceArSync
|
|
45
45
|
def self.namespaced(field)
|
46
46
|
SalesforceArSync.config["NAMESPACE_PREFIX"].present? ? :"#{SalesforceArSync.config["NAMESPACE_PREFIX"]}__#{field}" : :"#{field}"
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
|
+
# Get configuration for the in app deletions.
|
50
|
+
# Map to the object within the app if named differently then in SalesForce
|
51
|
+
def self.deletion_map(field)
|
52
|
+
SalesforceArSync.config['DELETION_MAP'].fetch(field, field)
|
53
|
+
end
|
54
|
+
|
49
55
|
private
|
50
56
|
|
51
57
|
def collect_sobjects
|
52
|
-
notification = @xml_hashed["Envelope"]["Body"]["notifications"]["Notification"]
|
58
|
+
notification = @xml_hashed["Envelope"]["Body"]["notifications"]["Notification"]
|
53
59
|
if notification.is_a? Array
|
54
60
|
return notification.collect{ |h| h["sObject"].symbolize_keys}
|
55
61
|
else
|
@@ -58,4 +64,4 @@ module SalesforceArSync
|
|
58
64
|
end
|
59
65
|
end
|
60
66
|
end
|
61
|
-
end
|
67
|
+
end
|
@@ -1,19 +1,21 @@
|
|
1
1
|
module SalesforceArSync
|
2
2
|
module SoapHandler
|
3
3
|
class Delete < SalesforceArSync::SoapHandler::Base
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
def process_notifications(priority = 90)
|
5
|
+
batch_process do |sobject|
|
6
|
+
SalesforceArSync::SoapHandler::Delete.delay(priority: priority, run_at: 5.seconds.from_now).delete_object(sobject)
|
7
|
+
end
|
8
|
+
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
def self.delete_object(hash = {})
|
11
|
+
raise ArgumentError, 'Object_Id__c parameter required' if hash[namespaced(:Object_Id__c)].blank?
|
12
|
+
raise ArgumentError, 'Object_Type__c parameter required' if hash[namespaced(:Object_Type__c)].blank?
|
13
|
+
raise Exception, "Deletion failed: No class found for #{hash[namespaced(:Object_Type__c)]}" unless deletion_map(hash[namespaced(:Object_Type__c)]).safe_constantize
|
14
|
+
|
15
|
+
object = deletion_map(hash[namespaced(:Object_Type__c)]).safe_constantize.try(:find_by_salesforce_id, hash[namespaced(:Object_Id__c)])
|
16
|
+
|
17
|
+
object.destroy if object && object.ar_sync_inbound_delete?
|
18
|
+
end
|
17
19
|
end
|
18
|
-
|
19
|
-
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: salesforce_ar_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Halliday
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2016-04-18 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
@@ -188,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
188
188
|
version: '0'
|
189
189
|
requirements: []
|
190
190
|
rubyforge_project:
|
191
|
-
rubygems_version: 2.
|
191
|
+
rubygems_version: 2.5.1
|
192
192
|
signing_key:
|
193
193
|
specification_version: 4
|
194
194
|
summary: ActiveRecord extension & rails engine for syncing data with Salesforce.com
|