active_force 0.7.0 → 0.15.0
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 +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 +122 -41
- data/CODEOWNERS +2 -0
- data/Gemfile +0 -1
- data/README.md +116 -16
- data/active_force.gemspec +11 -4
- data/lib/active_force/active_query.rb +107 -6
- data/lib/active_force/association/association.rb +48 -4
- 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 +75 -29
- data/lib/active_force/version.rb +3 -1
- data/lib/active_force.rb +9 -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 +253 -10
- data/spec/active_force/callbacks_spec.rb +1 -1
- 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 +11 -11
- data/spec/active_force/sobject_spec.rb +223 -16
- 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 -25
- data/lib/active_attr/dirty.rb +0 -24
- data/spec/active_force/attribute_spec.rb +0 -27
@@ -56,6 +56,28 @@ module ActiveForce
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
context 'has_one' do
|
61
|
+
let(:association){ HasOneAssociation.new(HasOneParent, :has_one_child) }
|
62
|
+
|
63
|
+
context 'with a value' do
|
64
|
+
let(:value) do
|
65
|
+
build_restforce_sobject 'Id' => '213'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns a child' do
|
69
|
+
expect(instance.build_relation_model).to be_a HasOneChild
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'without a value' do
|
74
|
+
let(:value){ nil }
|
75
|
+
|
76
|
+
it 'returns nil' do
|
77
|
+
expect(instance.build_relation_model).to be_nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
59
81
|
end
|
60
82
|
end
|
61
83
|
end
|
@@ -9,12 +9,20 @@ 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
|
15
23
|
|
16
24
|
before do
|
17
|
-
|
25
|
+
ActiveForce.sfdc_client = client
|
18
26
|
end
|
19
27
|
|
20
28
|
describe "has_many_query" do
|
@@ -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
|
@@ -5,7 +5,7 @@ module ActiveForce
|
|
5
5
|
let(:client){ double "client" }
|
6
6
|
|
7
7
|
before do
|
8
|
-
|
8
|
+
ActiveForce.sfdc_client = client
|
9
9
|
end
|
10
10
|
|
11
11
|
describe '.includes' do
|
@@ -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
|