salesforce_ar_sync 2.0.0 → 2.0.1
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.
- 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
|