restforce-db 1.2.6 → 1.2.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|