restforce-db 1.0.2 → 1.0.3
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/lib/restforce/db/attribute_map.rb +4 -1
- data/lib/restforce/db/synchronizer.rb +10 -2
- data/lib/restforce/db/version.rb +1 -1
- data/test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_no_associated_database_record/does_nothing_for_this_specific_mapping.yml +197 -0
- data/test/lib/restforce/db/attribute_map_test.rb +11 -0
- data/test/lib/restforce/db/synchronizer_test.rb +24 -13
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a757b3b70679ca9163fa7a856cc8e9f7228ce335
|
4
|
+
data.tar.gz: 0d6b4a908dccf33b1c15ad3c919c162a6de3411b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09a9d4fd95e92f629ac74e10efbef8e77011fb646f5548c813bf1d0375fcfcb4cb86eaca3cf3a22c94ec878f10b2f2dc2d0400e6a05600dc1a721ac2b9ad0d00
|
7
|
+
data.tar.gz: 78875a23c150314c0101a25b30cf9cd5c9bd4292853390290bbb396e587c1f4a9f7ea2cf4f0db9d8db0e4f1b6d744d5e3b4a679c1b87bcc7d807a7bb25c53b0c
|
@@ -79,7 +79,10 @@ module Restforce
|
|
79
79
|
when :salesforce
|
80
80
|
@fields.each_with_object({}) do |(attribute, mapping), converted|
|
81
81
|
next unless attributes.key?(attribute)
|
82
|
-
|
82
|
+
value = attributes[attribute]
|
83
|
+
value = value.respond_to?(:iso8601) ? value.utc.iso8601 : value
|
84
|
+
|
85
|
+
converted[mapping] = value
|
83
86
|
end
|
84
87
|
else
|
85
88
|
raise ArgumentError
|
@@ -18,6 +18,10 @@ module Restforce
|
|
18
18
|
# Public: Synchronize records for the current mapping from a Hash of
|
19
19
|
# record descriptors to attributes.
|
20
20
|
#
|
21
|
+
# NOTE: Synchronizer assumes that the propagation step has done its job
|
22
|
+
# correctly. If we can't locate a database record for a specific Salsforce
|
23
|
+
# ID, we assume it shouldn't be synchronized.
|
24
|
+
#
|
21
25
|
# changes - A Hash, with keys composed of a Salesforce ID and model name,
|
22
26
|
# with Restforce::DB::Accumulator objects as values.
|
23
27
|
#
|
@@ -26,8 +30,12 @@ module Restforce
|
|
26
30
|
changes.each do |(id, salesforce_model), accumulator|
|
27
31
|
next unless salesforce_model == @mapping.salesforce_model
|
28
32
|
|
29
|
-
|
30
|
-
|
33
|
+
database_instance = @mapping.database_record_type.find(id)
|
34
|
+
salesforce_instance = @mapping.salesforce_record_type.find(id)
|
35
|
+
next unless database_instance && salesforce_instance
|
36
|
+
|
37
|
+
update(database_instance, accumulator)
|
38
|
+
update(salesforce_instance, accumulator)
|
31
39
|
end
|
32
40
|
end
|
33
41
|
|
data/lib/restforce/db/version.rb
CHANGED
@@ -0,0 +1,197 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://<host>/services/oauth2/token
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: grant_type=password&client_id=<client_id>&client_secret=<client_secret>&username=<username>&password=<password><security_token>
|
9
|
+
headers:
|
10
|
+
User-Agent:
|
11
|
+
- Faraday v0.9.1
|
12
|
+
Content-Type:
|
13
|
+
- application/x-www-form-urlencoded
|
14
|
+
Accept-Encoding:
|
15
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
16
|
+
Accept:
|
17
|
+
- "*/*"
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Date:
|
24
|
+
- Fri, 10 Apr 2015 18:16:05 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=pcw4QakVSumA7tABeMs79A;Path=/;Domain=.salesforce.com;Expires=Tue,
|
27
|
+
09-Jun-2015 18:16:05 GMT
|
28
|
+
Expires:
|
29
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
30
|
+
Pragma:
|
31
|
+
- no-cache
|
32
|
+
Cache-Control:
|
33
|
+
- no-cache, no-store
|
34
|
+
Content-Type:
|
35
|
+
- application/json;charset=UTF-8
|
36
|
+
Transfer-Encoding:
|
37
|
+
- chunked
|
38
|
+
body:
|
39
|
+
encoding: ASCII-8BIT
|
40
|
+
string: '{"id":"https://login.salesforce.com/id/00D1a000000H3O9EAK/0051a000000UGT8AAO","issued_at":"1428689765521","token_type":"Bearer","instance_url":"https://<host>","signature":"iVn8K79ySw/26GQM8/ZHlQ7tE1l2EUH+WGphHVWkQFg=","access_token":"00D1a000000H3O9!AQ4AQO48p7VCPJTqs85KtBx3kEBjPhP.lCvkGK3ayiFCcg2H2nbFwdKZaBetwWzVAndOSywkSvoT7_YZEmwLnhtbJ1A3E5NZ"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Fri, 10 Apr 2015 18:16:05 GMT
|
43
|
+
- request:
|
44
|
+
method: post
|
45
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: '{"Name":"Custom object","Example_Field__c":"Some sample text"}'
|
49
|
+
headers:
|
50
|
+
User-Agent:
|
51
|
+
- Faraday v0.9.1
|
52
|
+
Content-Type:
|
53
|
+
- application/json
|
54
|
+
Authorization:
|
55
|
+
- OAuth 00D1a000000H3O9!AQ4AQO48p7VCPJTqs85KtBx3kEBjPhP.lCvkGK3ayiFCcg2H2nbFwdKZaBetwWzVAndOSywkSvoT7_YZEmwLnhtbJ1A3E5NZ
|
56
|
+
Accept-Encoding:
|
57
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
58
|
+
Accept:
|
59
|
+
- "*/*"
|
60
|
+
response:
|
61
|
+
status:
|
62
|
+
code: 201
|
63
|
+
message: Created
|
64
|
+
headers:
|
65
|
+
Date:
|
66
|
+
- Fri, 10 Apr 2015 18:16:05 GMT
|
67
|
+
Set-Cookie:
|
68
|
+
- BrowserId=I0vlITthQ-GdMURdX_Eu4A;Path=/;Domain=.salesforce.com;Expires=Tue,
|
69
|
+
09-Jun-2015 18:16:05 GMT
|
70
|
+
Expires:
|
71
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
72
|
+
Sforce-Limit-Info:
|
73
|
+
- api-usage=58/15000
|
74
|
+
Location:
|
75
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001LXBfAAO"
|
76
|
+
Content-Type:
|
77
|
+
- application/json;charset=UTF-8
|
78
|
+
Transfer-Encoding:
|
79
|
+
- chunked
|
80
|
+
body:
|
81
|
+
encoding: ASCII-8BIT
|
82
|
+
string: '{"id":"a001a000001LXBfAAO","success":true,"errors":[]}'
|
83
|
+
http_version:
|
84
|
+
recorded_at: Fri, 10 Apr 2015 18:16:05 GMT
|
85
|
+
- request:
|
86
|
+
method: get
|
87
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c%20where%20Id%20=%20%27a001a000001LXBfAAO%27
|
88
|
+
body:
|
89
|
+
encoding: US-ASCII
|
90
|
+
string: ''
|
91
|
+
headers:
|
92
|
+
User-Agent:
|
93
|
+
- Faraday v0.9.1
|
94
|
+
Authorization:
|
95
|
+
- OAuth 00D1a000000H3O9!AQ4AQO48p7VCPJTqs85KtBx3kEBjPhP.lCvkGK3ayiFCcg2H2nbFwdKZaBetwWzVAndOSywkSvoT7_YZEmwLnhtbJ1A3E5NZ
|
96
|
+
Accept-Encoding:
|
97
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
98
|
+
Accept:
|
99
|
+
- "*/*"
|
100
|
+
response:
|
101
|
+
status:
|
102
|
+
code: 200
|
103
|
+
message: OK
|
104
|
+
headers:
|
105
|
+
Date:
|
106
|
+
- Fri, 10 Apr 2015 18:16:05 GMT
|
107
|
+
Set-Cookie:
|
108
|
+
- BrowserId=KoiOz0-gSYiQzd8NJ4uMRQ;Path=/;Domain=.salesforce.com;Expires=Tue,
|
109
|
+
09-Jun-2015 18:16:05 GMT
|
110
|
+
Expires:
|
111
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
112
|
+
Sforce-Limit-Info:
|
113
|
+
- api-usage=58/15000
|
114
|
+
Content-Type:
|
115
|
+
- application/json;charset=UTF-8
|
116
|
+
Transfer-Encoding:
|
117
|
+
- chunked
|
118
|
+
body:
|
119
|
+
encoding: ASCII-8BIT
|
120
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LXBfAAO"},"Id":"a001a000001LXBfAAO","SystemModstamp":"2015-04-10T18:16:05.000+0000","Name":"Custom
|
121
|
+
object","Example_Field__c":"Some sample text"}]}'
|
122
|
+
http_version:
|
123
|
+
recorded_at: Fri, 10 Apr 2015 18:16:05 GMT
|
124
|
+
- request:
|
125
|
+
method: get
|
126
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c%20where%20Id%20=%20%27a001a000001LXBfAAO%27
|
127
|
+
body:
|
128
|
+
encoding: US-ASCII
|
129
|
+
string: ''
|
130
|
+
headers:
|
131
|
+
User-Agent:
|
132
|
+
- Faraday v0.9.1
|
133
|
+
Authorization:
|
134
|
+
- OAuth 00D1a000000H3O9!AQ4AQO48p7VCPJTqs85KtBx3kEBjPhP.lCvkGK3ayiFCcg2H2nbFwdKZaBetwWzVAndOSywkSvoT7_YZEmwLnhtbJ1A3E5NZ
|
135
|
+
Accept-Encoding:
|
136
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
137
|
+
Accept:
|
138
|
+
- "*/*"
|
139
|
+
response:
|
140
|
+
status:
|
141
|
+
code: 200
|
142
|
+
message: OK
|
143
|
+
headers:
|
144
|
+
Date:
|
145
|
+
- Fri, 10 Apr 2015 18:16:06 GMT
|
146
|
+
Set-Cookie:
|
147
|
+
- BrowserId=GS8k_s93SVmx-JpXvfVjPQ;Path=/;Domain=.salesforce.com;Expires=Tue,
|
148
|
+
09-Jun-2015 18:16:06 GMT
|
149
|
+
Expires:
|
150
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
151
|
+
Sforce-Limit-Info:
|
152
|
+
- api-usage=58/15000
|
153
|
+
Content-Type:
|
154
|
+
- application/json;charset=UTF-8
|
155
|
+
Transfer-Encoding:
|
156
|
+
- chunked
|
157
|
+
body:
|
158
|
+
encoding: ASCII-8BIT
|
159
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LXBfAAO"},"Id":"a001a000001LXBfAAO","SystemModstamp":"2015-04-10T18:16:05.000+0000","Name":"Custom
|
160
|
+
object","Example_Field__c":"Some sample text"}]}'
|
161
|
+
http_version:
|
162
|
+
recorded_at: Fri, 10 Apr 2015 18:16:06 GMT
|
163
|
+
- request:
|
164
|
+
method: delete
|
165
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001LXBfAAO
|
166
|
+
body:
|
167
|
+
encoding: US-ASCII
|
168
|
+
string: ''
|
169
|
+
headers:
|
170
|
+
User-Agent:
|
171
|
+
- Faraday v0.9.1
|
172
|
+
Authorization:
|
173
|
+
- OAuth 00D1a000000H3O9!AQ4AQO48p7VCPJTqs85KtBx3kEBjPhP.lCvkGK3ayiFCcg2H2nbFwdKZaBetwWzVAndOSywkSvoT7_YZEmwLnhtbJ1A3E5NZ
|
174
|
+
Accept-Encoding:
|
175
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
176
|
+
Accept:
|
177
|
+
- "*/*"
|
178
|
+
response:
|
179
|
+
status:
|
180
|
+
code: 204
|
181
|
+
message: No Content
|
182
|
+
headers:
|
183
|
+
Date:
|
184
|
+
- Fri, 10 Apr 2015 18:16:09 GMT
|
185
|
+
Set-Cookie:
|
186
|
+
- BrowserId=KJPi4MJTQ0mr8dA2ahBjEw;Path=/;Domain=.salesforce.com;Expires=Tue,
|
187
|
+
09-Jun-2015 18:16:09 GMT
|
188
|
+
Expires:
|
189
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
190
|
+
Sforce-Limit-Info:
|
191
|
+
- api-usage=58/15000
|
192
|
+
body:
|
193
|
+
encoding: UTF-8
|
194
|
+
string: ''
|
195
|
+
http_version:
|
196
|
+
recorded_at: Fri, 10 Apr 2015 18:16:09 GMT
|
197
|
+
recorded_with: VCR 2.9.3
|
@@ -55,6 +55,17 @@ describe Restforce::DB::AttributeMap do
|
|
55
55
|
it "performs no special conversion for database columns" do
|
56
56
|
expect(attribute_map.convert(database_model, attributes)).to_equal(attributes)
|
57
57
|
end
|
58
|
+
|
59
|
+
describe "when one of the attributes is a Date or Time" do
|
60
|
+
let(:timestamp) { Time.now }
|
61
|
+
let(:attributes) { { column_one: timestamp } }
|
62
|
+
|
63
|
+
it "converts the attribute to an ISO-8601 string for Salesforce" do
|
64
|
+
expect(attribute_map.convert(salesforce_model, attributes)).to_equal(
|
65
|
+
fields[attributes.keys.first] => timestamp.iso8601,
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
58
69
|
end
|
59
70
|
|
60
71
|
describe "#convert_from_salesforce" do
|
@@ -20,6 +20,30 @@ describe Restforce::DB::Synchronizer do
|
|
20
20
|
mapping.convert(salesforce_model, attributes),
|
21
21
|
)
|
22
22
|
end
|
23
|
+
let(:changes) { { [salesforce_id, salesforce_model] => accumulator } }
|
24
|
+
let(:new_attributes) do
|
25
|
+
{
|
26
|
+
"Name" => "Some new name",
|
27
|
+
"Example_Field__c" => "New sample text",
|
28
|
+
}
|
29
|
+
end
|
30
|
+
let(:accumulator) do
|
31
|
+
Restforce::DB::Accumulator.new.tap do |accumulator|
|
32
|
+
accumulator.store(Time.now, new_attributes)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "given a Salesforce record with no associated database record" do
|
37
|
+
before do
|
38
|
+
salesforce_id
|
39
|
+
synchronizer.run(changes)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "does nothing for this specific mapping" do
|
43
|
+
record = mapping.salesforce_record_type.find(salesforce_id)
|
44
|
+
expect(record.attributes).to_equal attributes
|
45
|
+
end
|
46
|
+
end
|
23
47
|
|
24
48
|
describe "given a Salesforce record with an associated database record" do
|
25
49
|
let(:database_attributes) do
|
@@ -33,19 +57,6 @@ describe Restforce::DB::Synchronizer do
|
|
33
57
|
database_model.create!(database_attributes.merge(salesforce_id: salesforce_id))
|
34
58
|
end
|
35
59
|
|
36
|
-
let(:changes) { { [salesforce_id, salesforce_model] => accumulator } }
|
37
|
-
let(:new_attributes) do
|
38
|
-
{
|
39
|
-
"Name" => "Some new name",
|
40
|
-
"Example_Field__c" => "New sample text",
|
41
|
-
}
|
42
|
-
end
|
43
|
-
let(:accumulator) do
|
44
|
-
Restforce::DB::Accumulator.new.tap do |accumulator|
|
45
|
-
accumulator.store(Time.now, new_attributes)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
60
|
before do
|
50
61
|
database_record
|
51
62
|
synchronizer.run(changes)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restforce-db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Horner
|
@@ -271,6 +271,7 @@ files:
|
|
271
271
|
- test/cassettes/Restforce_DB_Strategies_Always/_build_/given_a_Salesforce_record/with_a_corresponding_database_record/does_not_want_to_build_a_new_record.yml
|
272
272
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/updates_the_database_record.yml
|
273
273
|
- test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_an_associated_database_record/updates_the_salesforce_record.yml
|
274
|
+
- test/cassettes/Restforce_DB_Synchronizer/_run/given_a_Salesforce_record_with_no_associated_database_record/does_nothing_for_this_specific_mapping.yml
|
274
275
|
- test/lib/restforce/db/accumulator_test.rb
|
275
276
|
- test/lib/restforce/db/associations/active_record_test.rb
|
276
277
|
- test/lib/restforce/db/attribute_map_test.rb
|