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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1841b09cb85809cd87a0f6ae83a6447054b882a6
4
- data.tar.gz: 625a699341da7e4291c50ccb93fa20d2a0b03b0f
3
+ metadata.gz: d563ffb6d31cbe2705e07d8a67271e6d4f017024
4
+ data.tar.gz: ad9572805ba0250df541a763534894607d0221d0
5
5
  SHA512:
6
- metadata.gz: 1f8500084cc35f4bd96f51e0f9d8c5f3403c65affd1912bb96053ccc3f36c4191fabd449bcb20c6c4a00fb97c41b5dfcecd4384ccf4926985e18223eb5ebadc0
7
- data.tar.gz: 3b1d6678aa40b3959540454c3cf8c0f5cccc63a62fd3e59cbe2e2ad1800e5b1f9d88773be23da7db9203be048255f1811501e64731c68045838866fc98369032
6
+ metadata.gz: 0a598a642d31e556fea311df8f9d07222c20235734a73e3acd4ef725069416851507c4a5bc03398a05d7a7da79bedc3776d81f7f30f1510800f132f37c0128fb
7
+ data.tar.gz: 05b53d7e19460990822f2d56d1861a63bd3f694071db543111a84117d98bb78cc67ad8a42b66de41f4b34c5506215b9ac46c8b6130a6550bca17c4f236e177e2
data/lib/restforce/db.rb CHANGED
@@ -31,6 +31,7 @@ require "restforce/db/runner"
31
31
 
32
32
  require "restforce/db/accumulator"
33
33
  require "restforce/db/attribute_map"
34
+ require "restforce/db/cleaner"
34
35
  require "restforce/db/collector"
35
36
  require "restforce/db/initializer"
36
37
  require "restforce/db/mapping"
@@ -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
@@ -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
  #
@@ -3,7 +3,7 @@ module Restforce
3
3
  # :nodoc:
4
4
  module DB
5
5
 
6
- VERSION = "1.2.6"
6
+ VERSION = "1.2.7"
7
7
 
8
8
  end
9
9
 
@@ -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 |m|
24
- m.fields = { email: "Email" }
25
- m.associations << Restforce::DB::Associations::HasOne.new(
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 |m|
24
- m.fields = { name: "Name" }
25
- m.associations << Restforce::DB::Associations::BelongsTo.new(
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 |m|
25
- m.fields = { email: "Email" }
26
- m.associations << association
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 |m|
91
- m.fields = { name: "Name" }
92
- m.associations << Restforce::DB::Associations::BelongsTo.new(
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 |m|
21
- m.fields = fields
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 |m|
17
- m.fields = fields
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 |m|
51
- m.fields = { email: "Email" }
52
- m.associations << Restforce::DB::Associations::HasOne.new(
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 |m|
19
- m.fields = { name: "Name" }
20
- m.associations << Restforce::DB::Associations::BelongsTo.new(
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
  )
@@ -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 |m|
24
- m.conditions = conditions
25
- m.fields = fields
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.6
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-27 00:00:00.000000000 Z
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