active_force 0.7.1 → 0.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +107 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.mailmap +3 -0
- data/CHANGELOG.md +120 -42
- data/CODEOWNERS +2 -0
- data/Gemfile +0 -1
- data/README.md +100 -21
- data/active_force.gemspec +11 -4
- data/lib/active_force/active_query.rb +92 -6
- data/lib/active_force/association/association.rb +47 -3
- data/lib/active_force/association/belongs_to_association.rb +25 -11
- data/lib/active_force/association/eager_load_projection_builder.rb +9 -3
- data/lib/active_force/association/has_many_association.rb +19 -19
- data/lib/active_force/association/has_one_association.rb +30 -0
- data/lib/active_force/association/relation_model_builder.rb +1 -1
- data/lib/active_force/association.rb +6 -4
- data/lib/active_force/{attribute.rb → field.rb} +3 -3
- data/lib/active_force/mapping.rb +6 -32
- data/lib/active_force/query.rb +21 -2
- data/lib/active_force/sobject.rb +73 -28
- data/lib/active_force/version.rb +3 -1
- data/lib/active_force.rb +2 -0
- data/lib/active_model/type/salesforce/multipicklist.rb +29 -0
- data/lib/active_model/type/salesforce/percent.rb +22 -0
- data/lib/generators/active_force/model/model_generator.rb +32 -21
- data/lib/generators/active_force/model/templates/model.rb.erb +3 -1
- data/spec/active_force/active_query_spec.rb +200 -8
- data/spec/active_force/association/relation_model_builder_spec.rb +22 -0
- data/spec/active_force/association_spec.rb +252 -9
- data/spec/active_force/field_spec.rb +34 -0
- data/spec/active_force/query_spec.rb +26 -0
- data/spec/active_force/sobject/includes_spec.rb +10 -10
- data/spec/active_force/sobject_spec.rb +156 -14
- data/spec/fixtures/sobject/single_sobject_hash.yml +1 -1
- data/spec/spec_helper.rb +5 -2
- data/spec/support/bangwhiz.rb +7 -0
- data/spec/support/restforce_factories.rb +1 -1
- data/spec/support/sobjects.rb +17 -1
- data/spec/support/whizbang.rb +2 -2
- metadata +64 -26
- data/lib/active_attr/dirty.rb +0 -24
- data/spec/active_force/attribute_spec.rb +0 -27
@@ -9,6 +9,14 @@ describe ActiveForce::SObject do
|
|
9
9
|
Comment.new(id: "1", post_id: "1")
|
10
10
|
end
|
11
11
|
|
12
|
+
let :has_one_parent do
|
13
|
+
HasOneParent.new(id: '1', comment: "BAR")
|
14
|
+
end
|
15
|
+
|
16
|
+
let :has_one_child do
|
17
|
+
HasOneChild.new(id: '1', has_one_parent_id: '1')
|
18
|
+
end
|
19
|
+
|
12
20
|
let :client do
|
13
21
|
double("sfdc_client", query: [Restforce::Mash.new("Id" => 1)])
|
14
22
|
end
|
@@ -39,6 +47,19 @@ describe ActiveForce::SObject do
|
|
39
47
|
end
|
40
48
|
end
|
41
49
|
|
50
|
+
context 'when primary key is blank' do
|
51
|
+
let(:post) { Post.new }
|
52
|
+
|
53
|
+
it 'does not make any queries' do
|
54
|
+
post.comments.to_a
|
55
|
+
expect(client).not_to have_received :query
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'returns empty' do
|
59
|
+
expect(post.comments.to_a).to be_empty
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
42
63
|
context 'when the SObject is namespaced' do
|
43
64
|
let(:account){ Foo::Account.new(id: '1') }
|
44
65
|
|
@@ -85,6 +106,197 @@ describe ActiveForce::SObject do
|
|
85
106
|
soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PostId = '1')"
|
86
107
|
expect(post.comments.to_s).to eq soql
|
87
108
|
end
|
109
|
+
|
110
|
+
context 'when passing `model` option' do
|
111
|
+
before do
|
112
|
+
allow(Comment).to receive(:where).once.and_return([comment])
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'allows passing as a constant' do
|
116
|
+
Post.has_many :comments, model: Comment
|
117
|
+
expect { post.comments }.to_not raise_error
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'allows passing as a string' do
|
121
|
+
Post.has_many :comments, model: 'Comment'
|
122
|
+
expect { post.comments }.to_not raise_error
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "has_one_query" do
|
128
|
+
it "should respond to relation method" do
|
129
|
+
expect(has_one_parent).to respond_to(:has_one_child)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should return a the correct child object" do
|
133
|
+
expect(has_one_parent.has_one_child).to be_a HasOneChild
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'makes only one API call to fetch the associated object' do
|
137
|
+
has_one_parent.has_one_child.id
|
138
|
+
has_one_parent.has_one_child.id
|
139
|
+
expect(client).to have_received(:query).once
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'queries for a single record with the correct foreign key' do
|
143
|
+
expected = <<~SOQL.squish
|
144
|
+
SELECT Id, has_one_parent_id__c, FancyParentId FROM HasOneChild__c WHERE (has_one_parent_id__c = '1') LIMIT 1
|
145
|
+
SOQL
|
146
|
+
has_one_parent.has_one_child
|
147
|
+
expect(client).to have_received(:query).with(expected)
|
148
|
+
end
|
149
|
+
|
150
|
+
context 'when primary key is blank' do
|
151
|
+
let(:parent) { HasOneParent.new }
|
152
|
+
|
153
|
+
it 'does not make any queries' do
|
154
|
+
parent.has_one_child
|
155
|
+
expect(client).not_to have_received :query
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'returns nil' do
|
159
|
+
expect(parent.has_one_child).to be_nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "assignments" do
|
164
|
+
let(:has_one) do
|
165
|
+
has_one_parent = HasOneParent.new(id: '1')
|
166
|
+
has_one_parent.has_one_child = HasOneChild.new(id: '1')
|
167
|
+
has_one_parent
|
168
|
+
end
|
169
|
+
|
170
|
+
before do
|
171
|
+
expect(client).to_not receive(:query)
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'accepts assignment of an existing object as an association' do
|
175
|
+
expect(client).to_not receive(:query)
|
176
|
+
other_child = HasOneChild.new(id: '2')
|
177
|
+
has_one.has_one_child = other_child
|
178
|
+
expect(has_one.has_one_child.has_one_parent_id).to eq has_one.id
|
179
|
+
expect(has_one.has_one_child).to eq other_child
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'uses first element if given Array' do
|
183
|
+
first_child = HasOneChild.new(id: '2')
|
184
|
+
has_one.has_one_child = [first_child, HasOneChild.new(id: '3')]
|
185
|
+
expect(has_one.has_one_child.has_one_parent_id).to eq has_one.id
|
186
|
+
expect(has_one.has_one_child).to eq first_child
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'can desassociate an object by setting it as nil' do
|
190
|
+
old_child = has_one.has_one_child
|
191
|
+
has_one.has_one_child = nil
|
192
|
+
expect(old_child.has_one_parent_id).to eq nil
|
193
|
+
expect(has_one.has_one_child).to eq nil
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'when primary key is blank' do
|
197
|
+
let(:child) { HasOneChild.new }
|
198
|
+
let(:parent) { HasOneParent.new }
|
199
|
+
|
200
|
+
it 'accepts assignment' do
|
201
|
+
parent.has_one_child = child
|
202
|
+
expect(parent.has_one_child).to eq(child)
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'accepts reassignment' do
|
206
|
+
parent.has_one_child = child
|
207
|
+
other_child = HasOneChild.new(id: 'x')
|
208
|
+
parent.has_one_child = other_child
|
209
|
+
expect(parent.has_one_child).to eq(other_child)
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'accepts nil assignment' do
|
213
|
+
parent.has_one_child = child
|
214
|
+
parent.has_one_child = nil
|
215
|
+
expect(parent.has_one_child).to be_nil
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'assigns the first element if given an array' do
|
219
|
+
parent.has_one_child = [child, 'something else']
|
220
|
+
expect(parent.has_one_child).to eq(child)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context 'when the SObject is namespaced' do
|
226
|
+
let(:attachment){ Foo::Attachment.new(id: '1', lead_id: '2') }
|
227
|
+
let(:lead){ Foo::Lead.new(id: '2') }
|
228
|
+
|
229
|
+
it 'generates the correct query' do
|
230
|
+
expect(client).to receive(:query).with("SELECT Id, Lead_Id__c, LeadId FROM Attachment WHERE (Lead_Id__c = '2') LIMIT 1")
|
231
|
+
lead.attachment
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'instantiates the correct object' do
|
235
|
+
expect(lead.attachment).to be_instance_of(Foo::Attachment)
|
236
|
+
end
|
237
|
+
|
238
|
+
context 'when given a foreign key' do
|
239
|
+
let(:lead) { Foo::Lead.new(id: '2') }
|
240
|
+
|
241
|
+
it 'generates the correct query' do
|
242
|
+
expect(client).to receive(:query).with("SELECT Id, Lead_Id__c, LeadId FROM Attachment WHERE (LeadId = '2') LIMIT 1")
|
243
|
+
lead.fancy_attachment
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
describe 'has_one(options)' do
|
250
|
+
it 'allows passing a foreign key' do
|
251
|
+
HasOneParent.has_one :has_one_child, foreign_key: :fancy_parent_id
|
252
|
+
allow(has_one_parent).to receive(:id).and_return "2"
|
253
|
+
expect(client).to receive(:query).with("SELECT Id, has_one_parent_id__c, FancyParentId FROM HasOneChild__c WHERE (FancyParentId = '2') LIMIT 1")
|
254
|
+
has_one_parent.has_one_child
|
255
|
+
HasOneParent.has_one :has_one_child, foreign_key: :has_one_parent_id # reset association to original value
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'when passing `model` option' do
|
259
|
+
before do
|
260
|
+
allow(HasOneChild).to receive(:find_by).and_return(has_one_child)
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'allows passing as a constant' do
|
264
|
+
HasOneParent.has_one :has_one_child, model: HasOneChild
|
265
|
+
expect { has_one_parent.has_one_child }.to_not raise_error
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'allows passing as a string' do
|
269
|
+
HasOneParent.has_one :has_one_child, model: 'HasOneChild'
|
270
|
+
expect { has_one_parent.has_one_child }.to_not raise_error
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context "when passing 'scoped_as' option" do
|
275
|
+
it 'makes a only single query if called more than once' do
|
276
|
+
post.last_comment
|
277
|
+
post.last_comment
|
278
|
+
expect(client).to have_received(:query).once
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'applies the scope to the query' do
|
282
|
+
expected = <<~SOQL.squish
|
283
|
+
SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c
|
284
|
+
WHERE (NOT ((Body__c = NULL))) AND (PostId = '1') ORDER BY CreatedDate DESC LIMIT 1
|
285
|
+
SOQL
|
286
|
+
post.last_comment
|
287
|
+
expect(client).to have_received(:query).with(expected)
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'applies the scope to the query if the lambda takes an argument' do
|
291
|
+
post.title = 'test_post_title'
|
292
|
+
expected = <<~SOQL.squish
|
293
|
+
SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c
|
294
|
+
WHERE (Body__c = 'test_post_title') AND (PostId = '1') LIMIT 1
|
295
|
+
SOQL
|
296
|
+
post.repeat_comment
|
297
|
+
expect(client).to have_received(:query).with(expected)
|
298
|
+
end
|
299
|
+
end
|
88
300
|
end
|
89
301
|
|
90
302
|
describe "belongs_to" do
|
@@ -92,20 +304,25 @@ describe ActiveForce::SObject do
|
|
92
304
|
expect(comment.post).to be_instance_of(Post)
|
93
305
|
end
|
94
306
|
|
95
|
-
it "should allow to pass a foreign key as options" do
|
96
|
-
Comment.belongs_to :post, foreign_key: :fancy_post_id
|
97
|
-
allow(comment).to receive(:fancy_post_id).and_return "2"
|
98
|
-
expect(client).to receive(:query).with("SELECT Id, Title__c FROM Post__c WHERE (Id = '2') LIMIT 1")
|
99
|
-
comment.post
|
100
|
-
Comment.belongs_to :post # reset association to original value
|
101
|
-
end
|
102
|
-
|
103
307
|
it 'makes only one API call to fetch the associated object' do
|
104
308
|
expect(client).to receive(:query).once
|
105
309
|
comment.post
|
106
310
|
comment.post
|
107
311
|
end
|
108
312
|
|
313
|
+
context 'when foreign key is blank' do
|
314
|
+
let(:comment) { Comment.new(id: '1') }
|
315
|
+
|
316
|
+
it 'does not make any queries' do
|
317
|
+
comment.post
|
318
|
+
expect(client).not_to have_received :query
|
319
|
+
end
|
320
|
+
|
321
|
+
it 'returns nil' do
|
322
|
+
expect(comment.post).to be_nil
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
109
326
|
describe "assignments" do
|
110
327
|
let(:comment) do
|
111
328
|
comment = Comment.new(id: '1')
|
@@ -116,7 +333,7 @@ describe ActiveForce::SObject do
|
|
116
333
|
before do
|
117
334
|
expect(client).to_not receive(:query)
|
118
335
|
end
|
119
|
-
|
336
|
+
|
120
337
|
it 'accepts assignment of an existing object as an association' do
|
121
338
|
expect(client).to_not receive(:query)
|
122
339
|
other_post = Post.new(id: "2")
|
@@ -154,4 +371,30 @@ describe ActiveForce::SObject do
|
|
154
371
|
end
|
155
372
|
end
|
156
373
|
end
|
374
|
+
|
375
|
+
describe 'belongs_to(options)' do
|
376
|
+
it 'allows passing a foreign key' do
|
377
|
+
Comment.belongs_to :post, foreign_key: :fancy_post_id
|
378
|
+
allow(comment).to receive(:fancy_post_id).and_return "2"
|
379
|
+
expect(client).to receive(:query).with("SELECT Id, Title__c FROM Post__c WHERE (Id = '2') LIMIT 1")
|
380
|
+
comment.post
|
381
|
+
Comment.belongs_to :post # reset association to original value
|
382
|
+
end
|
383
|
+
|
384
|
+
context 'when passing `model` option' do
|
385
|
+
before do
|
386
|
+
allow(Post).to receive(:find).once.and_return(post)
|
387
|
+
end
|
388
|
+
|
389
|
+
it 'allows passing as a constant' do
|
390
|
+
Comment.belongs_to :post, model: Post
|
391
|
+
expect { comment.post.id }.to_not raise_error
|
392
|
+
end
|
393
|
+
|
394
|
+
it 'allows passing as a string' do
|
395
|
+
Comment.belongs_to :post, model: 'Post'
|
396
|
+
expect { comment.post.id }.to_not raise_error
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
157
400
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveForce::Field do
|
4
|
+
let(:field) { ActiveForce::Field }
|
5
|
+
|
6
|
+
describe 'initialize' do
|
7
|
+
let(:some_field) { field.new(:some_field) }
|
8
|
+
|
9
|
+
it 'should set "from" and "as" as default' do
|
10
|
+
expect(some_field.sfdc_name).to eq 'Some_Field__c'
|
11
|
+
expect(some_field.as).to eq :string
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should take values from the option parameter' do
|
15
|
+
other_field = field.new(:other_field, sfdc_name: 'OT__c', as: :integer)
|
16
|
+
expect(other_field.sfdc_name).to eq 'OT__c'
|
17
|
+
expect(other_field.as).to eq :integer
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'when the field is' do
|
22
|
+
it 'a datetime should return a string like "YYYY-MM-DDTHH:MM:SSZ"' do
|
23
|
+
current_time = DateTime.now
|
24
|
+
names = field.new(:time, as: :datetime)
|
25
|
+
expect(names.value_for_hash current_time).to eq current_time.to_fs(:iso8601)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'a datetime field whose value is nil' do
|
29
|
+
current_time = nil
|
30
|
+
names = field.new(:time, as: :datetime)
|
31
|
+
expect(names.value_for_hash current_time).to be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -48,6 +48,22 @@ describe ActiveForce::Query do
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
describe ".not" do
|
52
|
+
let(:subquery) { ActiveForce::Query.new 'table_name' }
|
53
|
+
|
54
|
+
it 'should add a not condition' do
|
55
|
+
expect(query.not(['condition1 = 1']).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (NOT ((condition1 = 1)))"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe ".or" do
|
60
|
+
let(:subquery) { ActiveForce::Query.new 'table_name' }
|
61
|
+
|
62
|
+
it 'should create an or condition' do
|
63
|
+
expect(query.where('condition1 = 1').where('condition2 = 2').or(subquery.where('condition3 = 3')).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (((condition1 = 1) AND (condition2 = 2)) OR ((condition3 = 3)))"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
51
67
|
describe ".limit" do
|
52
68
|
it "should add a limit to a query" do
|
53
69
|
expect(query.limit("25").to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
|
@@ -123,4 +139,14 @@ describe ActiveForce::Query do
|
|
123
139
|
expect(query.where("name = 'cool'").count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
|
124
140
|
end
|
125
141
|
end
|
142
|
+
|
143
|
+
describe ".sum" do
|
144
|
+
it "should return the query for summing the desired column" do
|
145
|
+
expect(query.sum(:field1).to_s).to eq 'SELECT sum(field1) FROM table_name'
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should work with a condition" do
|
149
|
+
expect(query.where("name = 'cool'").sum(:field1).to_s).to eq "SELECT sum(field1) FROM table_name WHERE (name = 'cool')"
|
150
|
+
end
|
151
|
+
end
|
126
152
|
end
|
@@ -46,7 +46,7 @@ module ActiveForce
|
|
46
46
|
context 'with namespaced SObjects' do
|
47
47
|
it 'queries the API for the associated record' do
|
48
48
|
soql = Salesforce::Territory.includes(:quota).where(id: '123').to_s
|
49
|
-
expect(soql).to eq "SELECT Id, QuotaId, WidgetId,
|
49
|
+
expect(soql).to eq "SELECT Id, QuotaId, WidgetId, QuotaId.Id FROM Territory WHERE (Id = '123')"
|
50
50
|
end
|
51
51
|
|
52
52
|
it "queries the API once to retrieve the object and its related one" do
|
@@ -54,7 +54,7 @@ module ActiveForce
|
|
54
54
|
"Id" => "123",
|
55
55
|
"QuotaId" => "321",
|
56
56
|
"WidgetId" => "321",
|
57
|
-
"
|
57
|
+
"QuotaId" => {
|
58
58
|
"Id" => "321"
|
59
59
|
}
|
60
60
|
})]
|
@@ -88,7 +88,7 @@ module ActiveForce
|
|
88
88
|
|
89
89
|
context 'when the class name does not match the SFDC entity name' do
|
90
90
|
let(:expected_soql) do
|
91
|
-
"SELECT Id, QuotaId, WidgetId,
|
91
|
+
"SELECT Id, QuotaId, WidgetId, WidgetId.Id FROM Territory WHERE (Id = '123')"
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'queries the API for the associated record' do
|
@@ -100,7 +100,7 @@ module ActiveForce
|
|
100
100
|
response = [build_restforce_sobject({
|
101
101
|
"Id" => "123",
|
102
102
|
"WidgetId" => "321",
|
103
|
-
"
|
103
|
+
"WidgetId" => {
|
104
104
|
"Id" => "321"
|
105
105
|
}
|
106
106
|
})]
|
@@ -115,7 +115,7 @@ module ActiveForce
|
|
115
115
|
context 'child to several parents' do
|
116
116
|
it 'queries the API for associated records' do
|
117
117
|
soql = Salesforce::Territory.includes(:quota, :widget).where(id: '123').to_s
|
118
|
-
expect(soql).to eq "SELECT Id, QuotaId, WidgetId,
|
118
|
+
expect(soql).to eq "SELECT Id, QuotaId, WidgetId, QuotaId.Id, WidgetId.Id FROM Territory WHERE (Id = '123')"
|
119
119
|
end
|
120
120
|
|
121
121
|
it "queries the API once to retrieve the object and its assocations" do
|
@@ -123,10 +123,10 @@ module ActiveForce
|
|
123
123
|
"Id" => "123",
|
124
124
|
"QuotaId" => "321",
|
125
125
|
"WidgetId" => "321",
|
126
|
-
"
|
126
|
+
"QuotaId" => {
|
127
127
|
"Id" => "321"
|
128
128
|
},
|
129
|
-
"
|
129
|
+
"WidgetId" => {
|
130
130
|
"Id" => "321"
|
131
131
|
}
|
132
132
|
})]
|
@@ -263,7 +263,7 @@ module ActiveForce
|
|
263
263
|
describe 'mixing belongs_to and has_many' do
|
264
264
|
it 'formulates the correct SOQL query' do
|
265
265
|
soql = Account.includes(:opportunities, :owner).where(id: '123').to_s
|
266
|
-
expect(soql).to eq "SELECT Id, OwnerId, (SELECT Id, AccountId FROM Opportunities),
|
266
|
+
expect(soql).to eq "SELECT Id, OwnerId, (SELECT Id, AccountId FROM Opportunities), OwnerId.Id FROM Account WHERE (Id = '123')"
|
267
267
|
end
|
268
268
|
|
269
269
|
it 'builds the associated objects and caches them' do
|
@@ -273,12 +273,12 @@ module ActiveForce
|
|
273
273
|
{'Id' => '213', 'AccountId' => '123'},
|
274
274
|
{'Id' => '214', 'AccountId' => '123'}
|
275
275
|
]),
|
276
|
-
'
|
276
|
+
'OwnerId' => {
|
277
277
|
'Id' => '321'
|
278
278
|
}
|
279
279
|
})]
|
280
280
|
allow(client).to receive(:query).once.and_return response
|
281
|
-
account = Account.includes(:opportunities).find '123'
|
281
|
+
account = Account.includes(:opportunities, :owner).find '123'
|
282
282
|
expect(account.opportunities).to be_an Array
|
283
283
|
expect(account.opportunities.all? { |o| o.is_a? Opportunity }).to eq true
|
284
284
|
expect(account.owner).to be_a Owner
|