restforce-db 1.2.6 → 1.2.7
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.rb +1 -0
- data/lib/restforce/db/cleaner.rb +72 -0
- data/lib/restforce/db/mapping.rb +16 -0
- data/lib/restforce/db/record_types/active_record.rb +10 -0
- data/lib/restforce/db/version.rb +1 -1
- data/lib/restforce/db/worker.rb +11 -0
- data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_does_not_meet_the_mapping_conditions/for_a_non-Passive_strategy/drops_the_synchronized_database_record.yml +200 -0
- data/test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_meets_the_mapping_conditions/does_not_drop_the_synchronized_database_record.yml +202 -0
- data/test/lib/restforce/db/associations/belongs_to_test.rb +3 -3
- data/test/lib/restforce/db/associations/has_many_test.rb +3 -3
- data/test/lib/restforce/db/associations/has_one_test.rb +6 -6
- data/test/lib/restforce/db/attribute_map_test.rb +2 -2
- data/test/lib/restforce/db/cleaner_test.rb +56 -0
- data/test/lib/restforce/db/mapping_test.rb +14 -2
- data/test/lib/restforce/db/record_types/active_record_test.rb +26 -3
- data/test/lib/restforce/db/strategies/associated_test.rb +3 -3
- data/test/support/utilities.rb +3 -3
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d563ffb6d31cbe2705e07d8a67271e6d4f017024
|
4
|
+
data.tar.gz: ad9572805ba0250df541a763534894607d0221d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a598a642d31e556fea311df8f9d07222c20235734a73e3acd4ef725069416851507c4a5bc03398a05d7a7da79bedc3776d81f7f30f1510800f132f37c0128fb
|
7
|
+
data.tar.gz: 05b53d7e19460990822f2d56d1861a63bd3f694071db543111a84117d98bb78cc67ad8a42b66de41f4b34c5506215b9ac46c8b6130a6550bca17c4f236e177e2
|
data/lib/restforce/db.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Restforce
|
2
|
+
|
3
|
+
module DB
|
4
|
+
|
5
|
+
# Restforce::DB::Cleaner is responsible for culling the matching database
|
6
|
+
# records when a Salesforce record no longer meets the sync conditions.
|
7
|
+
class Cleaner
|
8
|
+
|
9
|
+
# Public: Initialize a Restforce::DB::Cleaner.
|
10
|
+
#
|
11
|
+
# mapping - A Restforce::DB::Mapping.
|
12
|
+
# runner - A Restforce::DB::Runner.
|
13
|
+
def initialize(mapping, runner = Runner.new)
|
14
|
+
@mapping = mapping
|
15
|
+
@strategy = mapping.strategy
|
16
|
+
@runner = runner
|
17
|
+
end
|
18
|
+
|
19
|
+
# Public: Run the database culling loop for this mapping.
|
20
|
+
#
|
21
|
+
# Returns nothing.
|
22
|
+
def run
|
23
|
+
return if @strategy.passive?
|
24
|
+
@mapping.database_record_type.destroy_all(invalid_salesforce_ids)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# Internal: Get the IDs of records which are in the larger collection
|
30
|
+
# of Salesforce records, but which do not meet the specific conditions for
|
31
|
+
# this mapping.
|
32
|
+
#
|
33
|
+
# Returns an Array of IDs.
|
34
|
+
def invalid_salesforce_ids
|
35
|
+
all_salesforce_ids - valid_salesforce_ids
|
36
|
+
end
|
37
|
+
|
38
|
+
# Internal: Get the IDs of all recently-modified Salesforce records
|
39
|
+
# corresponding to the object type for this mapping.
|
40
|
+
#
|
41
|
+
# Returns an Array of IDs.
|
42
|
+
def all_salesforce_ids
|
43
|
+
all_ids = []
|
44
|
+
|
45
|
+
@mapping.unscoped do |map|
|
46
|
+
@runner.run(map) do |run|
|
47
|
+
run.salesforce_records { |record| all_ids << record.id }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
all_ids
|
52
|
+
end
|
53
|
+
|
54
|
+
# Internal: Get the IDs of the recently-modified Salesforce records which
|
55
|
+
# meet the conditions for this mapping.
|
56
|
+
#
|
57
|
+
# Returns an Array of IDs.
|
58
|
+
def valid_salesforce_ids
|
59
|
+
valid_ids = []
|
60
|
+
|
61
|
+
@runner.run(@mapping) do |run|
|
62
|
+
run.salesforce_records { |record| valid_ids << record.id }
|
63
|
+
end
|
64
|
+
|
65
|
+
valid_ids
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/lib/restforce/db/mapping.rb
CHANGED
@@ -87,6 +87,22 @@ module Restforce
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
+
# Public: Access the Mapping object without any conditions on the fetched
|
91
|
+
# records. Allows for a comparison of all modified records to only those
|
92
|
+
# modified records that still fit the `where` criteria.
|
93
|
+
#
|
94
|
+
# block - A block of code to execute in a condition-less context.
|
95
|
+
#
|
96
|
+
# Yields the Mapping with its conditions removed.
|
97
|
+
# Returns the result of the block.
|
98
|
+
def unscoped
|
99
|
+
criteria = @conditions
|
100
|
+
@conditions = []
|
101
|
+
yield self
|
102
|
+
ensure
|
103
|
+
@conditions = criteria
|
104
|
+
end
|
105
|
+
|
90
106
|
private
|
91
107
|
|
92
108
|
# Internal: Get an AttributeMap for the fields defined for this mapping.
|
@@ -66,6 +66,16 @@ module Restforce
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
# Public: Destroy all database records corresponding to the list of
|
70
|
+
# passed Salesforce IDs.
|
71
|
+
#
|
72
|
+
# ids - An Array of Salesforce IDs.
|
73
|
+
#
|
74
|
+
# Returns nothing.
|
75
|
+
def destroy_all(ids)
|
76
|
+
@record_type.where(@mapping.lookup_column => ids).destroy_all
|
77
|
+
end
|
78
|
+
|
69
79
|
# Public: Does the model represented by this record type have a column
|
70
80
|
# with the requested name?
|
71
81
|
#
|
data/lib/restforce/db/version.rb
CHANGED
data/lib/restforce/db/worker.rb
CHANGED
@@ -77,6 +77,7 @@ module Restforce
|
|
77
77
|
|
78
78
|
Restforce::DB::Registry.each do |mapping|
|
79
79
|
task("PROPAGATING RECORDS", mapping) { propagate mapping }
|
80
|
+
task("CLEANING RECORDS", mapping) { clean mapping }
|
80
81
|
task("COLLECTING CHANGES", mapping) { collect mapping }
|
81
82
|
end
|
82
83
|
|
@@ -130,6 +131,16 @@ module Restforce
|
|
130
131
|
Initializer.new(mapping, runner).run
|
131
132
|
end
|
132
133
|
|
134
|
+
# Internal: Remove synchronized records from the database when the
|
135
|
+
# Salesforce record no longer meets the mapping's conditions.
|
136
|
+
#
|
137
|
+
# mapping - A Restforce::DB::Mapping.
|
138
|
+
#
|
139
|
+
# Returns nothing.
|
140
|
+
def clean(mapping)
|
141
|
+
Cleaner.new(mapping, runner).run
|
142
|
+
end
|
143
|
+
|
133
144
|
# Internal: Collect a list of changes from recently-updated records for
|
134
145
|
# the passed mapping.
|
135
146
|
#
|
@@ -0,0 +1,200 @@
|
|
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
|
+
- Tue, 28 Apr 2015 22:35:20 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=Mv4KGAcATkaQUlaR0LmBiQ;Path=/;Domain=.salesforce.com;Expires=Sat,
|
27
|
+
27-Jun-2015 22:35:20 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":"1430260520482","token_type":"Bearer","instance_url":"https://<host>","signature":"yQWlkrP+VEy6cJMr8X01tKUcp3jJfdab28DpozcgRRk=","access_token":"00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Tue, 28 Apr 2015 22:35:20 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":"Are you going to Scarborough Fair?","Example_Field__c":"Parsley,
|
49
|
+
Sage, Rosemary, and Thyme."}'
|
50
|
+
headers:
|
51
|
+
User-Agent:
|
52
|
+
- Faraday v0.9.1
|
53
|
+
Content-Type:
|
54
|
+
- application/json
|
55
|
+
Authorization:
|
56
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
57
|
+
Accept-Encoding:
|
58
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
59
|
+
Accept:
|
60
|
+
- "*/*"
|
61
|
+
response:
|
62
|
+
status:
|
63
|
+
code: 201
|
64
|
+
message: Created
|
65
|
+
headers:
|
66
|
+
Date:
|
67
|
+
- Tue, 28 Apr 2015 22:35:20 GMT
|
68
|
+
Set-Cookie:
|
69
|
+
- BrowserId=3WUn9_WbQZGC6UHfLFxLmQ;Path=/;Domain=.salesforce.com;Expires=Sat,
|
70
|
+
27-Jun-2015 22:35:20 GMT
|
71
|
+
Expires:
|
72
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
73
|
+
Sforce-Limit-Info:
|
74
|
+
- api-usage=6/15000
|
75
|
+
Location:
|
76
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0KAAS"
|
77
|
+
Content-Type:
|
78
|
+
- application/json;charset=UTF-8
|
79
|
+
Transfer-Encoding:
|
80
|
+
- chunked
|
81
|
+
body:
|
82
|
+
encoding: ASCII-8BIT
|
83
|
+
string: '{"id":"a001a000001Sr0KAAS","success":true,"errors":[]}'
|
84
|
+
http_version:
|
85
|
+
recorded_at: Tue, 28 Apr 2015 22:35:20 GMT
|
86
|
+
- request:
|
87
|
+
method: get
|
88
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c
|
89
|
+
body:
|
90
|
+
encoding: US-ASCII
|
91
|
+
string: ''
|
92
|
+
headers:
|
93
|
+
User-Agent:
|
94
|
+
- Faraday v0.9.1
|
95
|
+
Authorization:
|
96
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
97
|
+
Accept-Encoding:
|
98
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
99
|
+
Accept:
|
100
|
+
- "*/*"
|
101
|
+
response:
|
102
|
+
status:
|
103
|
+
code: 200
|
104
|
+
message: OK
|
105
|
+
headers:
|
106
|
+
Date:
|
107
|
+
- Tue, 28 Apr 2015 22:35:21 GMT
|
108
|
+
Set-Cookie:
|
109
|
+
- BrowserId=z-eXo_idQN6fNmKWqkMjUQ;Path=/;Domain=.salesforce.com;Expires=Sat,
|
110
|
+
27-Jun-2015 22:35:21 GMT
|
111
|
+
Expires:
|
112
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
113
|
+
Sforce-Limit-Info:
|
114
|
+
- api-usage=5/15000
|
115
|
+
Content-Type:
|
116
|
+
- application/json;charset=UTF-8
|
117
|
+
Transfer-Encoding:
|
118
|
+
- chunked
|
119
|
+
body:
|
120
|
+
encoding: ASCII-8BIT
|
121
|
+
string: '{"totalSize":2,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LNK5AAO"},"Id":"a001a000001LNK5AAO","SystemModstamp":"2015-04-08T20:49:02.000+0000","Name":"Custom
|
122
|
+
object","Example_Field__c":"Some sample text"},{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0KAAS"},"Id":"a001a000001Sr0KAAS","SystemModstamp":"2015-04-28T22:35:20.000+0000","Name":"Are
|
123
|
+
you going to Scarborough Fair?","Example_Field__c":"Parsley, Sage, Rosemary,
|
124
|
+
and Thyme."}]}'
|
125
|
+
http_version:
|
126
|
+
recorded_at: Tue, 28 Apr 2015 22:35:21 GMT
|
127
|
+
- request:
|
128
|
+
method: get
|
129
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c%20where%20Name%20!=%20%27Are%20you%20going%20to%20Scarborough%20Fair?%27
|
130
|
+
body:
|
131
|
+
encoding: US-ASCII
|
132
|
+
string: ''
|
133
|
+
headers:
|
134
|
+
User-Agent:
|
135
|
+
- Faraday v0.9.1
|
136
|
+
Authorization:
|
137
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
138
|
+
Accept-Encoding:
|
139
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
140
|
+
Accept:
|
141
|
+
- "*/*"
|
142
|
+
response:
|
143
|
+
status:
|
144
|
+
code: 200
|
145
|
+
message: OK
|
146
|
+
headers:
|
147
|
+
Date:
|
148
|
+
- Tue, 28 Apr 2015 22:35:21 GMT
|
149
|
+
Set-Cookie:
|
150
|
+
- BrowserId=lCyOd81BQGCTyp4OGv1j6A;Path=/;Domain=.salesforce.com;Expires=Sat,
|
151
|
+
27-Jun-2015 22:35:21 GMT
|
152
|
+
Expires:
|
153
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
154
|
+
Sforce-Limit-Info:
|
155
|
+
- api-usage=5/15000
|
156
|
+
Content-Type:
|
157
|
+
- application/json;charset=UTF-8
|
158
|
+
Transfer-Encoding:
|
159
|
+
- chunked
|
160
|
+
body:
|
161
|
+
encoding: ASCII-8BIT
|
162
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LNK5AAO"},"Id":"a001a000001LNK5AAO","SystemModstamp":"2015-04-08T20:49:02.000+0000","Name":"Custom
|
163
|
+
object","Example_Field__c":"Some sample text"}]}'
|
164
|
+
http_version:
|
165
|
+
recorded_at: Tue, 28 Apr 2015 22:35:21 GMT
|
166
|
+
- request:
|
167
|
+
method: delete
|
168
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0KAAS
|
169
|
+
body:
|
170
|
+
encoding: US-ASCII
|
171
|
+
string: ''
|
172
|
+
headers:
|
173
|
+
User-Agent:
|
174
|
+
- Faraday v0.9.1
|
175
|
+
Authorization:
|
176
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
177
|
+
Accept-Encoding:
|
178
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
179
|
+
Accept:
|
180
|
+
- "*/*"
|
181
|
+
response:
|
182
|
+
status:
|
183
|
+
code: 204
|
184
|
+
message: No Content
|
185
|
+
headers:
|
186
|
+
Date:
|
187
|
+
- Tue, 28 Apr 2015 22:35:22 GMT
|
188
|
+
Set-Cookie:
|
189
|
+
- BrowserId=KOe6M7BRQ0-6dcG-gG0bEg;Path=/;Domain=.salesforce.com;Expires=Sat,
|
190
|
+
27-Jun-2015 22:35:22 GMT
|
191
|
+
Expires:
|
192
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
193
|
+
Sforce-Limit-Info:
|
194
|
+
- api-usage=5/15000
|
195
|
+
body:
|
196
|
+
encoding: UTF-8
|
197
|
+
string: ''
|
198
|
+
http_version:
|
199
|
+
recorded_at: Tue, 28 Apr 2015 22:35:22 GMT
|
200
|
+
recorded_with: VCR 2.9.3
|
@@ -0,0 +1,202 @@
|
|
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
|
+
- Tue, 28 Apr 2015 22:35:14 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=ATzeC8sYTiON60FmYuKong;Path=/;Domain=.salesforce.com;Expires=Sat,
|
27
|
+
27-Jun-2015 22:35:14 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":"1430260514286","token_type":"Bearer","instance_url":"https://<host>","signature":"8KSXxaHQWEXc7N8QF4D7sei0VTdPiA9Acov+SAqtAC0=","access_token":"00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Tue, 28 Apr 2015 22:35:14 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":"Are you going to Scarborough Fair?","Example_Field__c":"Parsley,
|
49
|
+
Sage, Rosemary, and Thyme."}'
|
50
|
+
headers:
|
51
|
+
User-Agent:
|
52
|
+
- Faraday v0.9.1
|
53
|
+
Content-Type:
|
54
|
+
- application/json
|
55
|
+
Authorization:
|
56
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
57
|
+
Accept-Encoding:
|
58
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
59
|
+
Accept:
|
60
|
+
- "*/*"
|
61
|
+
response:
|
62
|
+
status:
|
63
|
+
code: 201
|
64
|
+
message: Created
|
65
|
+
headers:
|
66
|
+
Date:
|
67
|
+
- Tue, 28 Apr 2015 22:35:14 GMT
|
68
|
+
Set-Cookie:
|
69
|
+
- BrowserId=7F5nncr9TF661qns_ENlfw;Path=/;Domain=.salesforce.com;Expires=Sat,
|
70
|
+
27-Jun-2015 22:35:14 GMT
|
71
|
+
Expires:
|
72
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
73
|
+
Sforce-Limit-Info:
|
74
|
+
- api-usage=5/15000
|
75
|
+
Location:
|
76
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0FAAS"
|
77
|
+
Content-Type:
|
78
|
+
- application/json;charset=UTF-8
|
79
|
+
Transfer-Encoding:
|
80
|
+
- chunked
|
81
|
+
body:
|
82
|
+
encoding: ASCII-8BIT
|
83
|
+
string: '{"id":"a001a000001Sr0FAAS","success":true,"errors":[]}'
|
84
|
+
http_version:
|
85
|
+
recorded_at: Tue, 28 Apr 2015 22:35:14 GMT
|
86
|
+
- request:
|
87
|
+
method: get
|
88
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c
|
89
|
+
body:
|
90
|
+
encoding: US-ASCII
|
91
|
+
string: ''
|
92
|
+
headers:
|
93
|
+
User-Agent:
|
94
|
+
- Faraday v0.9.1
|
95
|
+
Authorization:
|
96
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
97
|
+
Accept-Encoding:
|
98
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
99
|
+
Accept:
|
100
|
+
- "*/*"
|
101
|
+
response:
|
102
|
+
status:
|
103
|
+
code: 200
|
104
|
+
message: OK
|
105
|
+
headers:
|
106
|
+
Date:
|
107
|
+
- Tue, 28 Apr 2015 22:35:14 GMT
|
108
|
+
Set-Cookie:
|
109
|
+
- BrowserId=LPwX--hBSJ2-qXwhmGa1Rw;Path=/;Domain=.salesforce.com;Expires=Sat,
|
110
|
+
27-Jun-2015 22:35:14 GMT
|
111
|
+
Expires:
|
112
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
113
|
+
Sforce-Limit-Info:
|
114
|
+
- api-usage=5/15000
|
115
|
+
Content-Type:
|
116
|
+
- application/json;charset=UTF-8
|
117
|
+
Transfer-Encoding:
|
118
|
+
- chunked
|
119
|
+
body:
|
120
|
+
encoding: ASCII-8BIT
|
121
|
+
string: '{"totalSize":2,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LNK5AAO"},"Id":"a001a000001LNK5AAO","SystemModstamp":"2015-04-08T20:49:02.000+0000","Name":"Custom
|
122
|
+
object","Example_Field__c":"Some sample text"},{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0FAAS"},"Id":"a001a000001Sr0FAAS","SystemModstamp":"2015-04-28T22:35:14.000+0000","Name":"Are
|
123
|
+
you going to Scarborough Fair?","Example_Field__c":"Parsley, Sage, Rosemary,
|
124
|
+
and Thyme."}]}'
|
125
|
+
http_version:
|
126
|
+
recorded_at: Tue, 28 Apr 2015 22:35:14 GMT
|
127
|
+
- request:
|
128
|
+
method: get
|
129
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c%20from%20CustomObject__c
|
130
|
+
body:
|
131
|
+
encoding: US-ASCII
|
132
|
+
string: ''
|
133
|
+
headers:
|
134
|
+
User-Agent:
|
135
|
+
- Faraday v0.9.1
|
136
|
+
Authorization:
|
137
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
138
|
+
Accept-Encoding:
|
139
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
140
|
+
Accept:
|
141
|
+
- "*/*"
|
142
|
+
response:
|
143
|
+
status:
|
144
|
+
code: 200
|
145
|
+
message: OK
|
146
|
+
headers:
|
147
|
+
Date:
|
148
|
+
- Tue, 28 Apr 2015 22:35:14 GMT
|
149
|
+
Set-Cookie:
|
150
|
+
- BrowserId=zLWLapMfQDuUw4XC2ORLBw;Path=/;Domain=.salesforce.com;Expires=Sat,
|
151
|
+
27-Jun-2015 22:35:14 GMT
|
152
|
+
Expires:
|
153
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
154
|
+
Sforce-Limit-Info:
|
155
|
+
- api-usage=5/15000
|
156
|
+
Content-Type:
|
157
|
+
- application/json;charset=UTF-8
|
158
|
+
Transfer-Encoding:
|
159
|
+
- chunked
|
160
|
+
body:
|
161
|
+
encoding: ASCII-8BIT
|
162
|
+
string: '{"totalSize":2,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LNK5AAO"},"Id":"a001a000001LNK5AAO","SystemModstamp":"2015-04-08T20:49:02.000+0000","Name":"Custom
|
163
|
+
object","Example_Field__c":"Some sample text"},{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0FAAS"},"Id":"a001a000001Sr0FAAS","SystemModstamp":"2015-04-28T22:35:14.000+0000","Name":"Are
|
164
|
+
you going to Scarborough Fair?","Example_Field__c":"Parsley, Sage, Rosemary,
|
165
|
+
and Thyme."}]}'
|
166
|
+
http_version:
|
167
|
+
recorded_at: Tue, 28 Apr 2015 22:35:14 GMT
|
168
|
+
- request:
|
169
|
+
method: delete
|
170
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001Sr0FAAS
|
171
|
+
body:
|
172
|
+
encoding: US-ASCII
|
173
|
+
string: ''
|
174
|
+
headers:
|
175
|
+
User-Agent:
|
176
|
+
- Faraday v0.9.1
|
177
|
+
Authorization:
|
178
|
+
- OAuth 00D1a000000H3O9!AQ4AQKiSKdgqc4RvsFXyw8iT6exh89uDmXHSdoOm02DBwGRy9GlP_kVfG5FkxxjC_xd0GhiDTxOOu7j2B3K7FlG1lJo1IecI
|
179
|
+
Accept-Encoding:
|
180
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
181
|
+
Accept:
|
182
|
+
- "*/*"
|
183
|
+
response:
|
184
|
+
status:
|
185
|
+
code: 204
|
186
|
+
message: No Content
|
187
|
+
headers:
|
188
|
+
Date:
|
189
|
+
- Tue, 28 Apr 2015 22:35:15 GMT
|
190
|
+
Set-Cookie:
|
191
|
+
- BrowserId=wCjzqpiIQKGLi3e1ZCi2hA;Path=/;Domain=.salesforce.com;Expires=Sat,
|
192
|
+
27-Jun-2015 22:35:15 GMT
|
193
|
+
Expires:
|
194
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
195
|
+
Sforce-Limit-Info:
|
196
|
+
- api-usage=5/15000
|
197
|
+
body:
|
198
|
+
encoding: UTF-8
|
199
|
+
string: ''
|
200
|
+
http_version:
|
201
|
+
recorded_at: Tue, 28 Apr 2015 22:35:15 GMT
|
202
|
+
recorded_with: VCR 2.9.3
|
@@ -20,9 +20,9 @@ describe Restforce::DB::Associations::BelongsTo do
|
|
20
20
|
|
21
21
|
describe "with an inverse mapping", :vcr do
|
22
22
|
let(:inverse_mapping) do
|
23
|
-
Restforce::DB::Mapping.new(User, "Contact").tap do |
|
24
|
-
|
25
|
-
|
23
|
+
Restforce::DB::Mapping.new(User, "Contact").tap do |map|
|
24
|
+
map.fields = { email: "Email" }
|
25
|
+
map.associations << Restforce::DB::Associations::HasOne.new(
|
26
26
|
:custom_object,
|
27
27
|
through: "Friend__c",
|
28
28
|
)
|
@@ -20,9 +20,9 @@ describe Restforce::DB::Associations::HasMany do
|
|
20
20
|
|
21
21
|
describe "with an inverse mapping", :vcr do
|
22
22
|
let(:inverse_mapping) do
|
23
|
-
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |
|
24
|
-
|
25
|
-
|
23
|
+
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |map|
|
24
|
+
map.fields = { name: "Name" }
|
25
|
+
map.associations << Restforce::DB::Associations::BelongsTo.new(
|
26
26
|
:custom_object,
|
27
27
|
through: "CustomObject__c",
|
28
28
|
)
|
@@ -21,9 +21,9 @@ describe Restforce::DB::Associations::HasOne do
|
|
21
21
|
|
22
22
|
describe "with an inverse mapping", :vcr do
|
23
23
|
let(:inverse_mapping) do
|
24
|
-
Restforce::DB::Mapping.new(User, "Contact").tap do |
|
25
|
-
|
26
|
-
|
24
|
+
Restforce::DB::Mapping.new(User, "Contact").tap do |map|
|
25
|
+
map.fields = { email: "Email" }
|
26
|
+
map.associations << association
|
27
27
|
end
|
28
28
|
end
|
29
29
|
let(:user_salesforce_id) do
|
@@ -87,9 +87,9 @@ describe Restforce::DB::Associations::HasOne do
|
|
87
87
|
|
88
88
|
describe "and a nested association on the associated mapping" do
|
89
89
|
let(:nested_mapping) do
|
90
|
-
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |
|
91
|
-
|
92
|
-
|
90
|
+
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |map|
|
91
|
+
map.fields = { name: "Name" }
|
92
|
+
map.associations << Restforce::DB::Associations::BelongsTo.new(
|
93
93
|
:custom_object,
|
94
94
|
through: "CustomObject__c",
|
95
95
|
)
|
@@ -17,8 +17,8 @@ describe Restforce::DB::AttributeMap do
|
|
17
17
|
|
18
18
|
describe "#attributes" do
|
19
19
|
let(:mapping) do
|
20
|
-
Restforce::DB::Mapping.new(database_model, salesforce_model).tap do |
|
21
|
-
|
20
|
+
Restforce::DB::Mapping.new(database_model, salesforce_model).tap do |map|
|
21
|
+
map.fields = fields
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative "../../../test_helper"
|
2
|
+
|
3
|
+
describe Restforce::DB::Cleaner do
|
4
|
+
|
5
|
+
configure!
|
6
|
+
mappings!
|
7
|
+
|
8
|
+
let(:cleaner) { Restforce::DB::Cleaner.new(mapping) }
|
9
|
+
|
10
|
+
describe "#run", vcr: { match_requests_on: [:method, VCR.request_matchers.uri_without_param(:q)] } do
|
11
|
+
let(:attributes) do
|
12
|
+
{
|
13
|
+
name: "Are you going to Scarborough Fair?",
|
14
|
+
example: "Parsley, Sage, Rosemary, and Thyme.",
|
15
|
+
}
|
16
|
+
end
|
17
|
+
let(:salesforce_id) do
|
18
|
+
Salesforce.create!(
|
19
|
+
salesforce_model,
|
20
|
+
mapping.convert(salesforce_model, attributes),
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "given a synchronized Salesforce record" do
|
25
|
+
before do
|
26
|
+
database_model.create!(salesforce_id: salesforce_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when the record meets the mapping conditions" do
|
30
|
+
before do
|
31
|
+
cleaner.run
|
32
|
+
end
|
33
|
+
|
34
|
+
it "does not drop the synchronized database record" do
|
35
|
+
expect(database_model.last).to_not_be_nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "when the record does not meet the mapping conditions" do
|
40
|
+
before do
|
41
|
+
mapping.conditions = ["Name != '#{attributes[:name]}'"]
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "for a non-Passive strategy" do
|
45
|
+
before do
|
46
|
+
cleaner.run
|
47
|
+
end
|
48
|
+
|
49
|
+
it "drops the synchronized database record" do
|
50
|
+
expect(database_model.last).to_be_nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -13,8 +13,8 @@ describe Restforce::DB::Mapping do
|
|
13
13
|
}
|
14
14
|
end
|
15
15
|
let(:mapping) do
|
16
|
-
Restforce::DB::Mapping.new(database_model, salesforce_model).tap do |
|
17
|
-
|
16
|
+
Restforce::DB::Mapping.new(database_model, salesforce_model).tap do |map|
|
17
|
+
map.fields = fields
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -88,4 +88,16 @@ describe Restforce::DB::Mapping do
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
+
|
92
|
+
describe "#unscoped" do
|
93
|
+
before do
|
94
|
+
mapping.conditions = ["Some_Condition__c = TRUE"]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "removes the conditions from the mapping within the context of the block" do
|
98
|
+
expect(mapping.conditions).to_not_be :empty?
|
99
|
+
mapping.unscoped { |map| expect(map.conditions).to_be :empty? }
|
100
|
+
expect(mapping.conditions).to_not_be :empty?
|
101
|
+
end
|
102
|
+
end
|
91
103
|
end
|
@@ -47,9 +47,9 @@ describe Restforce::DB::RecordTypes::ActiveRecord do
|
|
47
47
|
through: "Friend__c",
|
48
48
|
)
|
49
49
|
|
50
|
-
associated_mapping = Restforce::DB::Mapping.new(User, "Contact").tap do |
|
51
|
-
|
52
|
-
|
50
|
+
associated_mapping = Restforce::DB::Mapping.new(User, "Contact").tap do |map|
|
51
|
+
map.fields = { email: "Email" }
|
52
|
+
map.associations << Restforce::DB::Associations::HasOne.new(
|
53
53
|
:custom_object,
|
54
54
|
through: "Friend__c",
|
55
55
|
)
|
@@ -92,4 +92,27 @@ describe Restforce::DB::RecordTypes::ActiveRecord do
|
|
92
92
|
expect(record_type.find("a001a000001E1vFAKE")).to_be_nil
|
93
93
|
end
|
94
94
|
end
|
95
|
+
|
96
|
+
describe "#destroy_all" do
|
97
|
+
before do
|
98
|
+
database_model.create!(salesforce_id: salesforce_id)
|
99
|
+
record_type.destroy_all(ids)
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "when the passed ids include the Salesforce ID of an existing record" do
|
103
|
+
let(:ids) { [salesforce_id] }
|
104
|
+
|
105
|
+
it "eliminates the matching record(s)" do
|
106
|
+
expect(database_model.last).to_be_nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "when the passed ids do not include the Salesforce ID of an existing record" do
|
111
|
+
let(:ids) { ["a001a000001E1vFAKE"] }
|
112
|
+
|
113
|
+
it "does not eliminate the matching record(s)" do
|
114
|
+
expect(database_model.last).to_not_be_nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
95
118
|
end
|
@@ -15,9 +15,9 @@ describe Restforce::DB::Strategies::Associated do
|
|
15
15
|
|
16
16
|
describe "given an inverse mapping" do
|
17
17
|
let(:inverse_mapping) do
|
18
|
-
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |
|
19
|
-
|
20
|
-
|
18
|
+
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |map|
|
19
|
+
map.fields = { name: "Name" }
|
20
|
+
map.associations << Restforce::DB::Associations::BelongsTo.new(
|
21
21
|
:custom_object,
|
22
22
|
through: "CustomObject__c",
|
23
23
|
)
|
data/test/support/utilities.rb
CHANGED
@@ -20,9 +20,9 @@ def mappings!
|
|
20
20
|
let(:fields) { { name: "Name", example: "Example_Field__c" } }
|
21
21
|
let(:conditions) { [] }
|
22
22
|
let(:mapping) do
|
23
|
-
Restforce::DB::Mapping.new(database_model, salesforce_model).tap do |
|
24
|
-
|
25
|
-
|
23
|
+
Restforce::DB::Mapping.new(database_model, salesforce_model).tap do |map|
|
24
|
+
map.conditions = conditions
|
25
|
+
map.fields = fields
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restforce-db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Horner
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -214,6 +214,7 @@ files:
|
|
214
214
|
- lib/restforce/db/associations/has_many.rb
|
215
215
|
- lib/restforce/db/associations/has_one.rb
|
216
216
|
- lib/restforce/db/attribute_map.rb
|
217
|
+
- lib/restforce/db/cleaner.rb
|
217
218
|
- lib/restforce/db/collector.rb
|
218
219
|
- lib/restforce/db/command.rb
|
219
220
|
- lib/restforce/db/configuration.rb
|
@@ -258,6 +259,8 @@ files:
|
|
258
259
|
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/when_no_salesforce_record_is_found_for_the_association/proceeds_without_constructing_any_records.yml
|
259
260
|
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_a_matching_associated_record_has_been_synchronized/returns_true.yml
|
260
261
|
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml
|
262
|
+
- test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_does_not_meet_the_mapping_conditions/for_a_non-Passive_strategy/drops_the_synchronized_database_record.yml
|
263
|
+
- test/cassettes/Restforce_DB_Cleaner/_run/given_a_synchronized_Salesforce_record/when_the_record_meets_the_mapping_conditions/does_not_drop_the_synchronized_database_record.yml
|
261
264
|
- test/cassettes/Restforce_DB_Collector/_run/given_a_Salesforce_record_with_an_associated_database_record/returns_the_attributes_from_both_records.yml
|
262
265
|
- test/cassettes/Restforce_DB_Collector/_run/given_an_existing_Salesforce_record/returns_the_attributes_from_the_Salesforce_record.yml
|
263
266
|
- test/cassettes/Restforce_DB_Collector/_run/given_an_existing_database_record/returns_the_attributes_from_the_database_record.yml
|
@@ -289,6 +292,7 @@ files:
|
|
289
292
|
- test/lib/restforce/db/associations/has_many_test.rb
|
290
293
|
- test/lib/restforce/db/associations/has_one_test.rb
|
291
294
|
- test/lib/restforce/db/attribute_map_test.rb
|
295
|
+
- test/lib/restforce/db/cleaner_test.rb
|
292
296
|
- test/lib/restforce/db/collector_test.rb
|
293
297
|
- test/lib/restforce/db/configuration_test.rb
|
294
298
|
- test/lib/restforce/db/dsl_test.rb
|