restforce-db 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/lib/restforce/db/associations/base.rb +25 -2
- data/lib/restforce/db/associations/belongs_to.rb +10 -16
- data/lib/restforce/db/associations/foreign_key.rb +2 -2
- data/lib/restforce/db/associations/has_many.rb +2 -2
- data/lib/restforce/db/associations/has_one.rb +1 -1
- data/lib/restforce/db/version.rb +1 -1
- data/test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/and_a_nested_association_on_the_associated_mapping/recursively_builds_all_associations.yml +389 -0
- data/test/lib/restforce/db/associations/belongs_to_test.rb +1 -1
- data/test/lib/restforce/db/associations/has_one_test.rb +42 -2
- data/test/lib/restforce/db/record_types/active_record_test.rb +2 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0949316bfb922720bc820e65d71b71dcaf830c47
|
4
|
+
data.tar.gz: 270a8d50a820d805316b0f3a54bf5386f3fbfdc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc8d66f4c534f6b683e074c35c0f74ad88eb2ed085866c7f28c46ea2ff2ec06dcf641e2cb459bc364ebaa188d7d7bbf3860d648df939d6b30a1174f9ba342761
|
7
|
+
data.tar.gz: e12dab58a707f332f69bcf63f2fdfa5752128566567ac73eeaaa1fb1ffd335c1b87820669e4539e9b7257269c551ce9682f6ad40f134b484a5a8c047141df341
|
data/README.md
CHANGED
@@ -145,6 +145,8 @@ Associations in `Restforce::DB` can be a little tricky, as they depend on your A
|
|
145
145
|
|
146
146
|
If your Salesforce objects have parity with your ActiveRecord models, your association mappings will likely have parity, as well. But, as demonstrated above, you should define your association mappings based on your Salesforce schema.
|
147
147
|
|
148
|
+
Associations can be nested arbitrarily, so it's not an issue to have several layers of `passive` record associations -- they'll all be created on initial sync.
|
149
|
+
|
148
150
|
##### `belongs_to`
|
149
151
|
|
150
152
|
This defines an association type in which the Lookup (i.e., foreign key) _is on the mapped Salesforce model_. In the example above, the `Restaurant__c` object type in Salesforce has two Lookup fields:
|
@@ -116,7 +116,7 @@ module Restforce
|
|
116
116
|
#
|
117
117
|
# Returns a Restforce::DB::Associations::Base.
|
118
118
|
def association_for(reflection)
|
119
|
-
inverse = reflection
|
119
|
+
inverse = inverse_association_name(reflection)
|
120
120
|
Registry[reflection.klass].detect do |mapping|
|
121
121
|
association = mapping.associations.detect { |a| a.name == inverse }
|
122
122
|
break association if association
|
@@ -133,10 +133,33 @@ module Restforce
|
|
133
133
|
database_record.association(name).scope
|
134
134
|
end
|
135
135
|
|
136
|
+
# Internal: Construct all associated records for the passed database
|
137
|
+
# record, based on the mapping represented by the passed Salesforce
|
138
|
+
# instance.
|
139
|
+
#
|
140
|
+
# parent_record - The parent of the associated_record; an instance
|
141
|
+
# of an ActiveRecord::Base subclass.
|
142
|
+
# associated_record - The child of the parent_record; an instance of
|
143
|
+
# an ActiveRecord::Base subclass.
|
144
|
+
# salesforce_instance - A Restforce::DB::Instances::Salesforce which
|
145
|
+
# corresponds to the associated_record.
|
146
|
+
#
|
147
|
+
# Returns an Array of associated records.
|
148
|
+
def nested_records(parent_record, database_record, salesforce_instance)
|
149
|
+
# We need to identify _this_ association to prevent backtracking.
|
150
|
+
inverse = inverse_association_name(target_reflection(parent_record))
|
151
|
+
nested = salesforce_instance.mapping.associations.flat_map do |a|
|
152
|
+
next if a.name == inverse
|
153
|
+
a.build(database_record, salesforce_instance.record)
|
154
|
+
end
|
155
|
+
|
156
|
+
nested.compact
|
157
|
+
end
|
158
|
+
|
136
159
|
# Internal: Get the Salesforce ID belonging to the associated record
|
137
160
|
# for a supplied instance. Must be implemented per-association.
|
138
161
|
#
|
139
|
-
# instance - A Restforce::DB::Instances::Base
|
162
|
+
# instance - A Restforce::DB::Instances::Base.
|
140
163
|
#
|
141
164
|
# Returns a String.
|
142
165
|
def associated_salesforce_id(_instance)
|
@@ -15,38 +15,32 @@ module Restforce
|
|
15
15
|
# database_record - An instance of an ActiveRecord::Base subclass.
|
16
16
|
# salesforce_record - A Hashie::Mash representing a Salesforce object.
|
17
17
|
#
|
18
|
-
# Returns
|
18
|
+
# Returns an Array of constructed association records.
|
19
19
|
def build(database_record, salesforce_record)
|
20
20
|
lookups = {}
|
21
|
+
instances = []
|
21
22
|
|
22
23
|
attributes = Registry[target_class(database_record)].inject({}) do |hash, mapping|
|
23
24
|
lookup_id = salesforce_record[lookup_field(mapping, database_record)]
|
24
|
-
|
25
25
|
lookups[mapping.lookup_column] = lookup_id
|
26
|
-
|
26
|
+
|
27
|
+
instance = mapping.salesforce_record_type.find(lookup_id)
|
28
|
+
instances << instance
|
29
|
+
|
30
|
+
hash.merge(mapping.convert(mapping.database_model, instance.attributes))
|
27
31
|
end
|
28
32
|
|
29
33
|
associated = association_scope(database_record).find_by(lookups)
|
30
34
|
associated ||= database_record.association(name).build(lookups)
|
31
35
|
|
32
36
|
associated.assign_attributes(attributes)
|
33
|
-
associated
|
37
|
+
nested = instances.flat_map { |i| nested_records(database_record, associated, i) }
|
38
|
+
|
39
|
+
[associated, *nested]
|
34
40
|
end
|
35
41
|
|
36
42
|
private
|
37
43
|
|
38
|
-
# Internal: Get a database-ready Hash of attributes from the Salesforce
|
39
|
-
# record identified by the passed lookup ID.
|
40
|
-
#
|
41
|
-
# mapping - A Restforce::DB::Mapping.
|
42
|
-
# lookup_id - A Lookup ID for the Salesforce record type in the Mapping.
|
43
|
-
#
|
44
|
-
# Returns a Hash.
|
45
|
-
def attributes_for(mapping, lookup_id)
|
46
|
-
salesforce_instance = mapping.salesforce_record_type.find(lookup_id)
|
47
|
-
mapping.convert(mapping.database_model, salesforce_instance.attributes)
|
48
|
-
end
|
49
|
-
|
50
44
|
# Internal: Get the Salesforce ID belonging to the associated record
|
51
45
|
# for a supplied instance. Must be implemented per-association.
|
52
46
|
#
|
@@ -39,7 +39,7 @@ module Restforce
|
|
39
39
|
# database_record - An instance of an ActiveRecord::Base subclass.
|
40
40
|
# salesforce_instance - A Restforce::DB::Instances::Salesforce.
|
41
41
|
#
|
42
|
-
# Returns
|
42
|
+
# Returns an Array of constructed associated objects.
|
43
43
|
def construct_for(database_record, salesforce_instance)
|
44
44
|
mapping = salesforce_instance.mapping
|
45
45
|
lookups = { mapping.lookup_column => salesforce_instance.id }
|
@@ -52,7 +52,7 @@ module Restforce
|
|
52
52
|
)
|
53
53
|
|
54
54
|
associated.assign_attributes(attributes)
|
55
|
-
associated
|
55
|
+
[associated, *nested_records(database_record, associated, salesforce_instance)]
|
56
56
|
end
|
57
57
|
|
58
58
|
# Internal: Get the Salesforce ID belonging to the associated record
|
@@ -15,7 +15,7 @@ module Restforce
|
|
15
15
|
# database_record - An instance of an ActiveRecord::Base subclass.
|
16
16
|
# salesforce_record - A Hashie::Mash representing a Salesforce object.
|
17
17
|
#
|
18
|
-
# Returns
|
18
|
+
# Returns an Array of constructed association records.
|
19
19
|
def build(database_record, salesforce_record)
|
20
20
|
target = target_mapping(database_record)
|
21
21
|
lookup_id = "#{lookup_field(target, database_record)} = '#{salesforce_record.Id}'"
|
@@ -25,7 +25,7 @@ module Restforce
|
|
25
25
|
records << construct_for(database_record, instance)
|
26
26
|
end
|
27
27
|
|
28
|
-
records
|
28
|
+
records.flatten
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
@@ -15,7 +15,7 @@ module Restforce
|
|
15
15
|
# database_record - An instance of an ActiveRecord::Base subclass.
|
16
16
|
# salesforce_record - A Hashie::Mash representing a Salesforce object.
|
17
17
|
#
|
18
|
-
# Returns
|
18
|
+
# Returns an Array of constructed association records.
|
19
19
|
def build(database_record, salesforce_record)
|
20
20
|
target = target_mapping(database_record)
|
21
21
|
query = "#{lookup_field(target, database_record)} = '#{salesforce_record.Id}'"
|
data/lib/restforce/db/version.rb
CHANGED
@@ -0,0 +1,389 @@
|
|
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
|
+
- Thu, 16 Apr 2015 19:25:59 GMT
|
25
|
+
Set-Cookie:
|
26
|
+
- BrowserId=wRO9AsU-SU6xl-dn4F8y0w;Path=/;Domain=.salesforce.com;Expires=Mon,
|
27
|
+
15-Jun-2015 19:25:59 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":"1429212359162","token_type":"Bearer","instance_url":"https://<host>","signature":"GigH5zHmZ1IsG+SaU0QdxmWhrvcKdrCm9X2rf1EkiwM=","access_token":"00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q"}'
|
41
|
+
http_version:
|
42
|
+
recorded_at: Thu, 16 Apr 2015 19:25:58 GMT
|
43
|
+
- request:
|
44
|
+
method: post
|
45
|
+
uri: https://<host>/services/data/v26.0/sobjects/Contact
|
46
|
+
body:
|
47
|
+
encoding: UTF-8
|
48
|
+
string: '{"Email":"somebody@example.com","LastName":"Somebody"}'
|
49
|
+
headers:
|
50
|
+
User-Agent:
|
51
|
+
- Faraday v0.9.1
|
52
|
+
Content-Type:
|
53
|
+
- application/json
|
54
|
+
Authorization:
|
55
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
56
|
+
Accept-Encoding:
|
57
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
58
|
+
Accept:
|
59
|
+
- "*/*"
|
60
|
+
response:
|
61
|
+
status:
|
62
|
+
code: 201
|
63
|
+
message: Created
|
64
|
+
headers:
|
65
|
+
Date:
|
66
|
+
- Thu, 16 Apr 2015 19:26:00 GMT
|
67
|
+
Set-Cookie:
|
68
|
+
- BrowserId=tRsiGzYzSMyKS0RqJbPpCw;Path=/;Domain=.salesforce.com;Expires=Mon,
|
69
|
+
15-Jun-2015 19:26:00 GMT
|
70
|
+
Expires:
|
71
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
72
|
+
Sforce-Limit-Info:
|
73
|
+
- api-usage=1/15000
|
74
|
+
Location:
|
75
|
+
- "/services/data/v26.0/sobjects/Contact/0031a000002JQEpAAO"
|
76
|
+
Content-Type:
|
77
|
+
- application/json;charset=UTF-8
|
78
|
+
Transfer-Encoding:
|
79
|
+
- chunked
|
80
|
+
body:
|
81
|
+
encoding: ASCII-8BIT
|
82
|
+
string: '{"id":"0031a000002JQEpAAO","success":true,"errors":[]}'
|
83
|
+
http_version:
|
84
|
+
recorded_at: Thu, 16 Apr 2015 19:26:00 GMT
|
85
|
+
- request:
|
86
|
+
method: post
|
87
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c
|
88
|
+
body:
|
89
|
+
encoding: UTF-8
|
90
|
+
string: '{"Friend__c":"0031a000002JQEpAAO"}'
|
91
|
+
headers:
|
92
|
+
User-Agent:
|
93
|
+
- Faraday v0.9.1
|
94
|
+
Content-Type:
|
95
|
+
- application/json
|
96
|
+
Authorization:
|
97
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
98
|
+
Accept-Encoding:
|
99
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
100
|
+
Accept:
|
101
|
+
- "*/*"
|
102
|
+
response:
|
103
|
+
status:
|
104
|
+
code: 201
|
105
|
+
message: Created
|
106
|
+
headers:
|
107
|
+
Date:
|
108
|
+
- Thu, 16 Apr 2015 19:26:01 GMT
|
109
|
+
Set-Cookie:
|
110
|
+
- BrowserId=y52TPTAuRN6fW06z37GcTQ;Path=/;Domain=.salesforce.com;Expires=Mon,
|
111
|
+
15-Jun-2015 19:26:01 GMT
|
112
|
+
Expires:
|
113
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
114
|
+
Sforce-Limit-Info:
|
115
|
+
- api-usage=2/15000
|
116
|
+
Location:
|
117
|
+
- "/services/data/v26.0/sobjects/CustomObject__c/a001a000001LoG1AAK"
|
118
|
+
Content-Type:
|
119
|
+
- application/json;charset=UTF-8
|
120
|
+
Transfer-Encoding:
|
121
|
+
- chunked
|
122
|
+
body:
|
123
|
+
encoding: ASCII-8BIT
|
124
|
+
string: '{"id":"a001a000001LoG1AAK","success":true,"errors":[]}'
|
125
|
+
http_version:
|
126
|
+
recorded_at: Thu, 16 Apr 2015 19:26:01 GMT
|
127
|
+
- request:
|
128
|
+
method: post
|
129
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObjectDetail__c
|
130
|
+
body:
|
131
|
+
encoding: UTF-8
|
132
|
+
string: '{"CustomObject__c":"a001a000001LoG1AAK"}'
|
133
|
+
headers:
|
134
|
+
User-Agent:
|
135
|
+
- Faraday v0.9.1
|
136
|
+
Content-Type:
|
137
|
+
- application/json
|
138
|
+
Authorization:
|
139
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
140
|
+
Accept-Encoding:
|
141
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
142
|
+
Accept:
|
143
|
+
- "*/*"
|
144
|
+
response:
|
145
|
+
status:
|
146
|
+
code: 201
|
147
|
+
message: Created
|
148
|
+
headers:
|
149
|
+
Date:
|
150
|
+
- Thu, 16 Apr 2015 19:26:02 GMT
|
151
|
+
Set-Cookie:
|
152
|
+
- BrowserId=cOGQueDpQNSZiHpqWIIf-g;Path=/;Domain=.salesforce.com;Expires=Mon,
|
153
|
+
15-Jun-2015 19:26:02 GMT
|
154
|
+
Expires:
|
155
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
156
|
+
Sforce-Limit-Info:
|
157
|
+
- api-usage=2/15000
|
158
|
+
Location:
|
159
|
+
- "/services/data/v26.0/sobjects/CustomObjectDetail__c/a011a000000hKfnAAE"
|
160
|
+
Content-Type:
|
161
|
+
- application/json;charset=UTF-8
|
162
|
+
Transfer-Encoding:
|
163
|
+
- chunked
|
164
|
+
body:
|
165
|
+
encoding: ASCII-8BIT
|
166
|
+
string: '{"id":"a011a000000hKfnAAE","success":true,"errors":[]}'
|
167
|
+
http_version:
|
168
|
+
recorded_at: Thu, 16 Apr 2015 19:26:02 GMT
|
169
|
+
- request:
|
170
|
+
method: get
|
171
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Email%20from%20Contact%20where%20Id%20=%20%270031a000002JQEpAAO%27
|
172
|
+
body:
|
173
|
+
encoding: US-ASCII
|
174
|
+
string: ''
|
175
|
+
headers:
|
176
|
+
User-Agent:
|
177
|
+
- Faraday v0.9.1
|
178
|
+
Authorization:
|
179
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
180
|
+
Accept-Encoding:
|
181
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
182
|
+
Accept:
|
183
|
+
- "*/*"
|
184
|
+
response:
|
185
|
+
status:
|
186
|
+
code: 200
|
187
|
+
message: OK
|
188
|
+
headers:
|
189
|
+
Date:
|
190
|
+
- Thu, 16 Apr 2015 19:26:03 GMT
|
191
|
+
Set-Cookie:
|
192
|
+
- BrowserId=7tPGpHZJQguC6IxoBKUgaw;Path=/;Domain=.salesforce.com;Expires=Mon,
|
193
|
+
15-Jun-2015 19:26:03 GMT
|
194
|
+
Expires:
|
195
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
196
|
+
Sforce-Limit-Info:
|
197
|
+
- api-usage=2/15000
|
198
|
+
Content-Type:
|
199
|
+
- application/json;charset=UTF-8
|
200
|
+
Transfer-Encoding:
|
201
|
+
- chunked
|
202
|
+
body:
|
203
|
+
encoding: ASCII-8BIT
|
204
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"Contact","url":"/services/data/v26.0/sobjects/Contact/0031a000002JQEpAAO"},"Id":"0031a000002JQEpAAO","SystemModstamp":"2015-04-16T19:26:00.000+0000","Email":"somebody@example.com"}]}'
|
205
|
+
http_version:
|
206
|
+
recorded_at: Thu, 16 Apr 2015 19:26:03 GMT
|
207
|
+
- request:
|
208
|
+
method: get
|
209
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20Example_Field__c,%20Friend__c%20from%20CustomObject__c%20where%20Friend__c%20=%20%270031a000002JQEpAAO%27
|
210
|
+
body:
|
211
|
+
encoding: US-ASCII
|
212
|
+
string: ''
|
213
|
+
headers:
|
214
|
+
User-Agent:
|
215
|
+
- Faraday v0.9.1
|
216
|
+
Authorization:
|
217
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
218
|
+
Accept-Encoding:
|
219
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
220
|
+
Accept:
|
221
|
+
- "*/*"
|
222
|
+
response:
|
223
|
+
status:
|
224
|
+
code: 200
|
225
|
+
message: OK
|
226
|
+
headers:
|
227
|
+
Date:
|
228
|
+
- Thu, 16 Apr 2015 19:26:04 GMT
|
229
|
+
Set-Cookie:
|
230
|
+
- BrowserId=0GBZp5d6Q4W9oYJ2xCoqPA;Path=/;Domain=.salesforce.com;Expires=Mon,
|
231
|
+
15-Jun-2015 19:26:04 GMT
|
232
|
+
Expires:
|
233
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
234
|
+
Sforce-Limit-Info:
|
235
|
+
- api-usage=2/15000
|
236
|
+
Content-Type:
|
237
|
+
- application/json;charset=UTF-8
|
238
|
+
Transfer-Encoding:
|
239
|
+
- chunked
|
240
|
+
body:
|
241
|
+
encoding: ASCII-8BIT
|
242
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObject__c","url":"/services/data/v26.0/sobjects/CustomObject__c/a001a000001LoG1AAK"},"Id":"a001a000001LoG1AAK","SystemModstamp":"2015-04-16T19:26:01.000+0000","Name":"a001a000001LoG1","Example_Field__c":null,"Friend__c":"0031a000002JQEpAAO"}]}'
|
243
|
+
http_version:
|
244
|
+
recorded_at: Thu, 16 Apr 2015 19:26:04 GMT
|
245
|
+
- request:
|
246
|
+
method: get
|
247
|
+
uri: https://<host>/services/data/v26.0/query?q=select%20Id,%20SystemModstamp,%20Name,%20CustomObject__c%20from%20CustomObjectDetail__c%20where%20CustomObject__c%20=%20%27a001a000001LoG1AAK%27
|
248
|
+
body:
|
249
|
+
encoding: US-ASCII
|
250
|
+
string: ''
|
251
|
+
headers:
|
252
|
+
User-Agent:
|
253
|
+
- Faraday v0.9.1
|
254
|
+
Authorization:
|
255
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
256
|
+
Accept-Encoding:
|
257
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
258
|
+
Accept:
|
259
|
+
- "*/*"
|
260
|
+
response:
|
261
|
+
status:
|
262
|
+
code: 200
|
263
|
+
message: OK
|
264
|
+
headers:
|
265
|
+
Date:
|
266
|
+
- Thu, 16 Apr 2015 19:26:05 GMT
|
267
|
+
Set-Cookie:
|
268
|
+
- BrowserId=RScD8n0tQn6Ka40Q_zj2pw;Path=/;Domain=.salesforce.com;Expires=Mon,
|
269
|
+
15-Jun-2015 19:26:05 GMT
|
270
|
+
Expires:
|
271
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
272
|
+
Sforce-Limit-Info:
|
273
|
+
- api-usage=2/15000
|
274
|
+
Content-Type:
|
275
|
+
- application/json;charset=UTF-8
|
276
|
+
Transfer-Encoding:
|
277
|
+
- chunked
|
278
|
+
body:
|
279
|
+
encoding: ASCII-8BIT
|
280
|
+
string: '{"totalSize":1,"done":true,"records":[{"attributes":{"type":"CustomObjectDetail__c","url":"/services/data/v26.0/sobjects/CustomObjectDetail__c/a011a000000hKfnAAE"},"Id":"a011a000000hKfnAAE","SystemModstamp":"2015-04-16T19:26:02.000+0000","Name":"a011a000000hKfn","CustomObject__c":"a001a000001LoG1AAK"}]}'
|
281
|
+
http_version:
|
282
|
+
recorded_at: Thu, 16 Apr 2015 19:26:05 GMT
|
283
|
+
- request:
|
284
|
+
method: delete
|
285
|
+
uri: https://<host>/services/data/v26.0/sobjects/Contact/0031a000002JQEpAAO
|
286
|
+
body:
|
287
|
+
encoding: US-ASCII
|
288
|
+
string: ''
|
289
|
+
headers:
|
290
|
+
User-Agent:
|
291
|
+
- Faraday v0.9.1
|
292
|
+
Authorization:
|
293
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
294
|
+
Accept-Encoding:
|
295
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
296
|
+
Accept:
|
297
|
+
- "*/*"
|
298
|
+
response:
|
299
|
+
status:
|
300
|
+
code: 204
|
301
|
+
message: No Content
|
302
|
+
headers:
|
303
|
+
Date:
|
304
|
+
- Thu, 16 Apr 2015 19:26:06 GMT
|
305
|
+
Set-Cookie:
|
306
|
+
- BrowserId=NEH4ouAkSbmwL7ARdAXr7Q;Path=/;Domain=.salesforce.com;Expires=Mon,
|
307
|
+
15-Jun-2015 19:26:06 GMT
|
308
|
+
Expires:
|
309
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
310
|
+
Sforce-Limit-Info:
|
311
|
+
- api-usage=3/15000
|
312
|
+
body:
|
313
|
+
encoding: UTF-8
|
314
|
+
string: ''
|
315
|
+
http_version:
|
316
|
+
recorded_at: Thu, 16 Apr 2015 19:26:07 GMT
|
317
|
+
- request:
|
318
|
+
method: delete
|
319
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObject__c/a001a000001LoG1AAK
|
320
|
+
body:
|
321
|
+
encoding: US-ASCII
|
322
|
+
string: ''
|
323
|
+
headers:
|
324
|
+
User-Agent:
|
325
|
+
- Faraday v0.9.1
|
326
|
+
Authorization:
|
327
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
328
|
+
Accept-Encoding:
|
329
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
330
|
+
Accept:
|
331
|
+
- "*/*"
|
332
|
+
response:
|
333
|
+
status:
|
334
|
+
code: 204
|
335
|
+
message: No Content
|
336
|
+
headers:
|
337
|
+
Date:
|
338
|
+
- Thu, 16 Apr 2015 19:26:08 GMT
|
339
|
+
Set-Cookie:
|
340
|
+
- BrowserId=JR1qDjLqR9Kbaw5KhQpGjA;Path=/;Domain=.salesforce.com;Expires=Mon,
|
341
|
+
15-Jun-2015 19:26:08 GMT
|
342
|
+
Expires:
|
343
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
344
|
+
Sforce-Limit-Info:
|
345
|
+
- api-usage=4/15000
|
346
|
+
body:
|
347
|
+
encoding: UTF-8
|
348
|
+
string: ''
|
349
|
+
http_version:
|
350
|
+
recorded_at: Thu, 16 Apr 2015 19:26:08 GMT
|
351
|
+
- request:
|
352
|
+
method: delete
|
353
|
+
uri: https://<host>/services/data/v26.0/sobjects/CustomObjectDetail__c/a011a000000hKfnAAE
|
354
|
+
body:
|
355
|
+
encoding: US-ASCII
|
356
|
+
string: ''
|
357
|
+
headers:
|
358
|
+
User-Agent:
|
359
|
+
- Faraday v0.9.1
|
360
|
+
Authorization:
|
361
|
+
- OAuth 00D1a000000H3O9!AQ4AQPSOXZt5DLhfr69D_LCpoJzz_hcsgL5M3__5XXvOQMahZ5HtzzBveYd9BpdCGejgkgFYX6_ZfJkTvkaXqAWbAEpg555q
|
362
|
+
Accept-Encoding:
|
363
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
364
|
+
Accept:
|
365
|
+
- "*/*"
|
366
|
+
response:
|
367
|
+
status:
|
368
|
+
code: 404
|
369
|
+
message: Not Found
|
370
|
+
headers:
|
371
|
+
Date:
|
372
|
+
- Thu, 16 Apr 2015 19:26:09 GMT
|
373
|
+
Set-Cookie:
|
374
|
+
- BrowserId=W0ivBZ6NTiSQA8J2bL7lgw;Path=/;Domain=.salesforce.com;Expires=Mon,
|
375
|
+
15-Jun-2015 19:26:09 GMT
|
376
|
+
Expires:
|
377
|
+
- Thu, 01 Jan 1970 00:00:00 GMT
|
378
|
+
Sforce-Limit-Info:
|
379
|
+
- api-usage=4/15000
|
380
|
+
Content-Type:
|
381
|
+
- application/json;charset=UTF-8
|
382
|
+
Transfer-Encoding:
|
383
|
+
- chunked
|
384
|
+
body:
|
385
|
+
encoding: UTF-8
|
386
|
+
string: '[{"message":"entity is deleted","errorCode":"ENTITY_IS_DELETED","fields":[]}]'
|
387
|
+
http_version:
|
388
|
+
recorded_at: Thu, 16 Apr 2015 19:26:09 GMT
|
389
|
+
recorded_with: VCR 2.9.3
|
@@ -69,7 +69,7 @@ describe Restforce::DB::Associations::BelongsTo do
|
|
69
69
|
describe "#build" do
|
70
70
|
let(:database_record) { CustomObject.new }
|
71
71
|
let(:salesforce_record) { mapping.salesforce_record_type.find(object_salesforce_id).record }
|
72
|
-
let(:associated) { association.build(database_record, salesforce_record) }
|
72
|
+
let(:associated) { association.build(database_record, salesforce_record).first }
|
73
73
|
|
74
74
|
it "returns an associated record, populated with the Salesforce attributes" do
|
75
75
|
expect(associated.custom_object).to_equal database_record
|
@@ -71,8 +71,48 @@ describe Restforce::DB::Associations::HasOne do
|
|
71
71
|
let(:associated) { association.build(database_record, salesforce_record) }
|
72
72
|
|
73
73
|
it "returns an associated record, populated with the Salesforce attributes" do
|
74
|
-
|
75
|
-
expect(
|
74
|
+
object = associated.first
|
75
|
+
expect(object.user).to_equal database_record
|
76
|
+
expect(object.salesforce_id).to_equal object_salesforce_id
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "and a nested association on the associated mapping" do
|
80
|
+
let(:nested_mapping) do
|
81
|
+
Restforce::DB::Mapping.new(Detail, "CustomObjectDetail__c").tap do |m|
|
82
|
+
m.fields = { name: "Name" }
|
83
|
+
m.associations << Restforce::DB::Associations::BelongsTo.new(
|
84
|
+
:custom_object,
|
85
|
+
through: "CustomObject__c",
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
let(:nested_association) do
|
90
|
+
Restforce::DB::Associations::HasMany.new(:details, through: "CustomObject__c")
|
91
|
+
end
|
92
|
+
let(:detail_salesforce_id) do
|
93
|
+
Salesforce.create!(
|
94
|
+
nested_mapping.salesforce_model,
|
95
|
+
"CustomObject__c" => object_salesforce_id,
|
96
|
+
)
|
97
|
+
end
|
98
|
+
|
99
|
+
before do
|
100
|
+
Restforce::DB::Registry << nested_mapping
|
101
|
+
mapping.associations << nested_association
|
102
|
+
end
|
103
|
+
|
104
|
+
it "recursively builds all associations" do
|
105
|
+
detail_salesforce_id
|
106
|
+
expect(associated.length).to_equal 2
|
107
|
+
|
108
|
+
object, detail = associated
|
109
|
+
|
110
|
+
expect(object).to_be_instance_of CustomObject
|
111
|
+
expect(object.user).to_equal database_record
|
112
|
+
|
113
|
+
expect(detail).to_be_instance_of Detail
|
114
|
+
expect(detail.custom_object).to_equal object
|
115
|
+
end
|
76
116
|
end
|
77
117
|
end
|
78
118
|
end
|
@@ -60,9 +60,10 @@ describe Restforce::DB::RecordTypes::ActiveRecord do
|
|
60
60
|
|
61
61
|
# Stub out the `#find` method on the record type
|
62
62
|
def salesforce_record_type.find(id)
|
63
|
-
Struct.new(:id, :last_update, :attributes).new(
|
63
|
+
Struct.new(:id, :last_update, :mapping, :attributes).new(
|
64
64
|
id,
|
65
65
|
Time.now,
|
66
|
+
Restforce::DB::Registry[User].first,
|
66
67
|
email: "somebody@example.com",
|
67
68
|
)
|
68
69
|
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.1
|
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-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -246,6 +246,7 @@ files:
|
|
246
246
|
- test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_build/builds_a_number_of_associated_records_from_the_data_in_Salesforce.yml
|
247
247
|
- test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_synced_for_/when_a_matching_associated_record_has_been_synchronized/returns_true.yml
|
248
248
|
- test/cassettes/Restforce_DB_Associations_HasMany/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml
|
249
|
+
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/and_a_nested_association_on_the_associated_mapping/recursively_builds_all_associations.yml
|
249
250
|
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_build/returns_an_associated_record_populated_with_the_Salesforce_attributes.yml
|
250
251
|
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_a_matching_associated_record_has_been_synchronized/returns_true.yml
|
251
252
|
- test/cassettes/Restforce_DB_Associations_HasOne/with_an_inverse_mapping/_synced_for_/when_no_matching_associated_record_has_been_synchronized/returns_false.yml
|