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 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