Skip to content

Commit 13db7d1

Browse files
MCWEB-2374: Manual Parameter Syncing (#39)
* Added the option to manually sync attributes, updated test suite and docs * Bumped version to 5.2.0 * Bumped version to 5.2.0 in docs * Fixed a bug where pristine attributes could not be force synced * Made sure forcibly synced async attributes use the SalesforceObjectSyncJob * Added gem push automation
1 parent df821f8 commit 13db7d1

15 files changed

Lines changed: 208 additions & 72 deletions

File tree

.github/workflows/gem-push.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Ruby Gem
2+
on:
3+
push:
4+
tags:
5+
- 'v[0-9]+.[0-9]+.[0-9]+*'
6+
jobs:
7+
build:
8+
if: ${{ github.event.base_ref == 'refs/heads/master' }}
9+
name: Build + Publish
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: read
13+
packages: write
14+
steps:
15+
- name: Echo GitHub Event Ref
16+
run: echo "${{ github.event.base_ref }}"
17+
- uses: actions/checkout@v4
18+
- name: Set up Ruby
19+
uses: ruby/setup-ruby@v1
20+
with:
21+
ruby-version: 3.3.6
22+
- name: Publish to GPR
23+
run: |
24+
mkdir -p $HOME/.gem
25+
touch $HOME/.gem/credentials
26+
chmod 0600 $HOME/.gem/credentials
27+
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
28+
gem build *.gemspec
29+
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
30+
env:
31+
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
32+
OWNER: ${{ github.repository_owner }}
33+
- name: Publish to RubyGems
34+
run: |
35+
mkdir -p $HOME/.gem
36+
touch $HOME/.gem/credentials
37+
chmod 0600 $HOME/.gem/credentials
38+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
39+
gem build *.gemspec
40+
gem push *.gem
41+
env:
42+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"

Appraisals

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
appraise "rails-4.0" do
2-
gem "rails", "4.0.4"
1+
appraise 'rails-7.1' do
2+
gem 'rails', '~> 7.1.0'
33
end
44

5-
appraise "rails-4.1" do
6-
gem "rails", "4.1.1"
5+
appraise 'rails-7.2' do
6+
gem 'rails', '~> 7.2.0'
77
end
88

9-
appraise "rails-4.2" do
10-
gem "rails", "4.2.1"
11-
end
9+
appraise 'rails-8.0' do
10+
gem 'rails', '~> 8.0.0'
11+
end

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,47 @@
11
# Version 1.1.0
22
* Salesforce objects you wish to sync no longer need to be materialized
33
* Requires that `SF_CLIENT` be initialized in your databasedotcom configuration
4+
45
# Version 1.1.1
56
* Adds missed paths to the gemspec to fix initialization issues when used as a gem
7+
68
# Version 1.1.2
79
* Adds support for namespaced Salesforce apps
10+
811
# Version 1.1.3
912
* Adds support for outbound deletions
1013
* Adds ability to configure inbound/outbound deletions on a per model basis
14+
1115
# Version 1.1.4
1216
* Fix issue with multi-select picklists introduced when using REST API
17+
1318
# Version 2.0.0
1419
* Add active record web id field
1520
* Moved from Rails 3 to Rails 4
21+
1622
# Version 2.0.1
1723
* Add the ability to map delete messages to any model without modifying the outbound message in Salesforce
24+
1825
# Version 2.0.2
1926
* Updated IP address ranges for Salesforce.
27+
2028
# Version 3.2.0
2129
* Adds support for Rails 5
2230
* Added ability to specify readonly fields for salesforce syncable models so those fields don't try to sync back to Salesforce
2331
* WebID syncing fixed
32+
2433
# Version 4.0.0
2534
* Changed Databasedotcom over to Restforce
35+
2636
# Version 4.1.0
2737
* Add rexml dependency to support Ruby 3.0
38+
2839
# Version 5.0.0
2940
* Replace .delay calls with ActiveJobs
3041
* Add job_queue config
42+
3143
# Version 5.1.0
3244
* Updated Psych Processing
45+
46+
# Version 5.2.0
47+
* Added the ability to manually trigger syncing of specific model attributes.

Gemfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ source 'https://rubygems.org'
22

33
gemspec
44

5-
gem "appraisal"
5+
gem 'appraisal'
6+
gem 'debug'

README.md

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,56 @@
33
SalesforceARSync allows you to sync models and fields with Salesforce through a combination of
44
Outbound Messaging, SOAP and restforce.
55

6+
### Contents
7+
8+
- [Installation](#installation)
9+
- [Requirements](#requirements)
10+
- [Salesforce Setup](#salesforce-setup)
11+
- [1. Setup Remote Access](#1-setup-remote-access)
12+
- [2. Setup Outbound Messaging](#2-setup-outbound-messaging)
13+
- [restforce](#restforce)
14+
- [Gem Installation](#gem-installation)
15+
- [Application Setup](#application-setup)
16+
- [Usage](#usage)
17+
- [Configuration Options](#configuration-options)
18+
- [Model Options](#model-options)
19+
- [salesforce\_sync\_enabled](#salesforce_sync_enabled)
20+
- [sync\_attributes](#sync_attributes)
21+
- [async\_attributes](#async_attributes)
22+
- [default\_attributes\_for\_create](#default_attributes_for_create)
23+
- [salesforce\_id\_attribute\_name](#salesforce_id_attribute_name)
24+
- [web\_id\_attribute\_name](#web_id_attribute_name)
25+
- [activerecord\_web\_id\_attribute\_name](#activerecord_web_id_attribute_name)
26+
- [salesforce\_sync\_web\_id](#salesforce_sync_web_id)
27+
- [additional\_lookup\_fields](#additional_lookup_fields)
28+
- [web\_class\_name](#web_class_name)
29+
- [salesforce\_object\_name](#salesforce_object_name)
30+
- [except](#except)
31+
- [save\_method](#save_method)
32+
- [unscoped\_updates](#unscoped_updates)
33+
- [readonly\_fields](#readonly_fields)
34+
- [Stopping the Sync](#stopping-the-sync)
35+
- [Manual Sync](#manual-sync)
36+
- [Examples](#examples)
37+
- [Our Basic Example Model](#our-basic-example-model)
38+
- [Making the Model Syncable](#making-the-model-syncable)
39+
- [Stopping the Model from Syncing with a Flag](#stopping-the-model-from-syncing-with-a-flag)
40+
- [Stopping the Model from Syncing with a Method](#stopping-the-model-from-syncing-with-a-method)
41+
- [Stopping a Record from Syncing](#stopping-a-record-from-syncing)
42+
- [Specify Async Attributes](#specify-async-attributes)
43+
- [Specify Default Attributes when an Object is Created](#specify-default-attributes-when-an-object-is-created)
44+
- [Relationships](#relationships)
45+
- [Defining a Custom Salesforce Object](#defining-a-custom-salesforce-object)
46+
- [Deletes](#deletes)
47+
- [Inbound Deletes](#inbound-deletes)
48+
- [Outbound Deletes](#outbound-deletes)
49+
- [Soft Deletes](#soft-deletes)
50+
- [Errors](#errors)
51+
- [Outbound Message Errors](#outbound-message-errors)
52+
- [Finding your 18 Character Organization ID](#finding-your-18-character-organization-id)
53+
- [Testing](#testing)
54+
- [Contributing](#contributing)
55+
656
## Installation
757

858
### Requirements
@@ -144,35 +194,6 @@ An example of adding an aliased object to the deletion map should look like the
144194
Account: 'YourModelName'
145195

146196
### Model Options
147-
The model can have several options set:
148-
149-
[__salesforce_sync_enabled__](#salesforce_sync_enabled)
150-
151-
[__sync_attributes__](#sync_attributes)
152-
153-
[__async_attributes__](#async_attributes)
154-
155-
[__default_attributes_for_create__](#default_attributes_for_create)
156-
157-
[__salesforce_id_attribute_name__](#salesforce_id_attribute_name)
158-
159-
[__web_id_attribute_name__](#web_id_attribute_name)
160-
161-
[__activerecord_web_id_attribute_name__](#activerecord_web_id_attribute_name)
162-
163-
[__salesforce_sync_web_id__](#salesforce_sync_web_id)
164-
165-
[__web_class_name__](#web_class_name)
166-
167-
[__salesforce_object_name__](#salesforce_object_name)
168-
169-
[__except__](#except)
170-
171-
[__save_method__](#save_method)
172-
173-
[__unscoped_updates__](#unscoped_updates)
174-
175-
[__readonly_fields__](#readonly_fields)
176197

177198
#### <a id="salesforce_sync_enabled"></a>salesforce_sync_enabled
178199
Model level option to enable disable the sync, defaults to true.
@@ -285,7 +306,7 @@ unscoped_updates: true
285306
````
286307

287308
#### readonly_fields
288-
Optionally set fields on the salesforce object that have been defined as Read Only in Salesforce.
309+
Optionally set fields on the salesforce object that have been defined as Read Only in Salesforce.
289310
This helps to ensure that those fields are not synced from the model to salesforce (but still syncable the other way).
290311
Accepts the salesforce field, not the model's fields.
291312

@@ -302,6 +323,16 @@ configuration variable _SALESFORCE_AR_SYNC_CONFIG["SYNC_ENABLED"]_
302323
* The model level by setting the _:salesforce_sync_enabled => false_ or _:except => :method_name_
303324
* The instance level by setting _:salesforce_skip_sync => true_ in the instance
304325

326+
### Manual Sync
327+
328+
You can trigger a manual sync of any configured attributes. All checks to skip syncing or to sync asynchronously will still be executed.
329+
330+
```ruby
331+
my_user_record.salesforce_sync(:email)
332+
333+
my_user_record.salesforce_sync(:email, :phone)
334+
```
335+
305336
## Examples
306337

307338
### Our Basic Example Model
@@ -500,6 +531,11 @@ If the SOAP handler encounters an error it will be recorded in the log of the ou
500531
it to an 18 character id by running it through the tool located here:
501532
http://cloudjedi.wordpress.com/no-fuss-salesforce-id-converter/ or by installing the Force.com Utility Belt for Chrome.
502533

534+
## Testing
535+
This gem uses [Appraisal](https://github.com/thoughtbot/appraisal) to test against many versions of Rails.
536+
537+
Run the test script to automatically set up and run the test suite: `./test`
538+
503539
## Contributing
504540

505541
1. Fork it
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
source "https://rubygems.org"
44

55
gem "appraisal"
6-
gem "rails", "4.0.4"
6+
gem "debug"
7+
gem "rails", "~> 7.1.0"
78

8-
gemspec :path => "../"
9+
gemspec path: "../"
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
source "https://rubygems.org"
44

55
gem "appraisal"
6-
gem "rails", "4.1.1"
6+
gem "debug"
7+
gem "rails", "~> 7.2.0"
78

8-
gemspec :path => "../"
9+
gemspec path: "../"
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
source "https://rubygems.org"
44

55
gem "appraisal"
6-
gem "rails", "4.2.1"
7-
gem 'mime-types', '2.6.2'
6+
gem "debug"
7+
gem "rails", "~> 8.0.0"
88

9-
gemspec :path => "../"
9+
gemspec path: "../"

lib/salesforce_ar_sync/salesforce_sync.rb

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,6 @@ def salesforce_process_update(attributes = {})
139139
self.send(self.class.salesforce_save_method)
140140
end
141141

142-
# def salesforce_object_exists?
143-
# return salesforce_object_exists_method if respond_to? salesforce_exists_method
144-
# return salesforce_object_exists_default
145-
# end
146-
147142
# Finds a salesforce record by its Id and returns nil or its SystemModstamp
148143
def system_mod_stamp
149144
sobject = SF_CLIENT.find(salesforce_object_name, salesforce_id)
@@ -161,10 +156,10 @@ def salesforce_should_update_attribute?(attribute)
161156
end
162157

163158
# create a hash of updates to send to salesforce
164-
def salesforce_attributes_to_update(include_all = false)
159+
def salesforce_attributes_to_update(include_all = false, attrs = [])
165160
{}.tap do |hash|
166161
self.class.salesforce_sync_attribute_mapping.each do |key, value|
167-
next unless respond_to?(value)
162+
next if (attrs.any? && attrs.exclude?(value.to_sym)) || !respond_to?(value)
168163

169164
# Checkboxes in SFDC Cannot be nil. Here we check for boolean field type and set nil values to be false
170165
attribute_value = send(value)
@@ -210,21 +205,27 @@ def ar_sync_outbound_delete?
210205

211206
# if attributes specified in the async_attributes array are the only attributes being modified, then sync the data
212207
# via delayed_job
213-
def salesforce_perform_async_call?
214-
return false if salesforce_attributes_to_update.empty? || self.class.salesforce_async_attributes.empty?
215-
salesforce_attributes_to_update.keys.all? { |key| self.class.salesforce_async_attributes.include?(key) } && salesforce_id.present?
208+
def salesforce_perform_async_call?(attributes_to_update)
209+
return false if attributes_to_update.empty? || self.class.salesforce_async_attributes.empty?
210+
attributes_to_update.keys.all? { |key| self.class.salesforce_async_attributes.include?(key) } && salesforce_id.present?
216211
end
217212

218213
# sync model data to Salesforce, adding any Salesforce validation errors to the models errors
219-
def salesforce_sync
214+
def salesforce_sync(*attrs)
220215
return if salesforce_skip_sync?
221-
if salesforce_perform_async_call?
222-
SalesforceArSync::SalesforceObjectSyncJob.set(priority: 50).perform_later(self.class.salesforce_web_class_name, salesforce_id, salesforce_attributes_to_update.to_json)
216+
217+
attributes_to_update = salesforce_attributes_to_update(attrs.any?, attrs)
218+
219+
if salesforce_perform_async_call?(attributes_to_update)
220+
SalesforceArSync::SalesforceObjectSyncJob.set(priority: 50).perform_later(
221+
self.class.salesforce_web_class_name, salesforce_id,
222+
attributes_to_update.to_json
223+
)
223224
else
224225
if salesforce_object_exists?
225-
salesforce_update_object(salesforce_attributes_to_update) if salesforce_attributes_to_update.present?
226+
salesforce_update_object(attributes_to_update) if attributes_to_update.present?
226227
else
227-
salesforce_create_object(salesforce_attributes_to_update(!new_record?)) if salesforce_id.nil?
228+
salesforce_create_object(attributes_to_update(!new_record?)) if salesforce_id.nil?
228229
end
229230
end
230231
rescue Exception => ex

lib/salesforce_ar_sync/version.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# frozen_string_literal: true
2+
13
module SalesforceArSync
2-
VERSION = '5.1.0'
4+
VERSION = '5.2.0'
35
end

0 commit comments

Comments
 (0)