active_force 0.15.1 → 0.17.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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +15 -0
- data/lib/active_force/active_query.rb +21 -32
- data/lib/active_force/association/belongs_to_association.rb +5 -1
- data/lib/active_force/association/eager_load_builder_for_nested_includes.rb +84 -0
- data/lib/active_force/association/eager_load_projection_builder.rb +15 -8
- data/lib/active_force/association/relation_model_builder.rb +10 -8
- data/lib/active_force/association.rb +1 -0
- data/lib/active_force/query.rb +30 -24
- data/lib/active_force/sobject.rb +10 -6
- data/lib/active_force/version.rb +1 -1
- data/spec/active_force/active_query_spec.rb +101 -59
- data/spec/active_force/association_spec.rb +11 -1
- data/spec/active_force/query_spec.rb +60 -5
- data/spec/active_force/sobject/includes_spec.rb +325 -0
- data/spec/active_force/sobject_spec.rb +69 -6
- data/spec/support/sobjects.rb +41 -0
- metadata +7 -6
@@ -285,6 +285,331 @@ module ActiveForce
|
|
285
285
|
expect(account.owner.id).to eq '321'
|
286
286
|
end
|
287
287
|
end
|
288
|
+
|
289
|
+
context 'when invalid associations are passed' do
|
290
|
+
it 'raises an error' do
|
291
|
+
expect { Quota.includes(:invalid).find('123') }.to raise_error(ActiveForce::Association::InvalidAssociationError, 'Association named invalid was not found on Quota')
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe '.includes with nested associations' do
|
297
|
+
|
298
|
+
context 'with custom objects' do
|
299
|
+
it 'formulates the correct SOQL query' do
|
300
|
+
soql = Quota.includes(prez_clubs: :club_members).where(id: '123').to_s
|
301
|
+
expect(soql).to eq <<-SOQL.squish
|
302
|
+
SELECT Id, Bar_Id__c,
|
303
|
+
(SELECT Id, QuotaId,
|
304
|
+
(SELECT Id, Name, Email FROM ClubMembers__r)
|
305
|
+
FROM PrezClubs__r)
|
306
|
+
FROM Quota__c
|
307
|
+
WHERE (Bar_Id__c = '123')
|
308
|
+
SOQL
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'builds the associated objects and caches them' do
|
312
|
+
response = [build_restforce_sobject({
|
313
|
+
'Id' => '123',
|
314
|
+
'PrezClubs__r' => build_restforce_collection([
|
315
|
+
{'Id' => '213', 'QuotaId' => '123', 'ClubMembers__r' => build_restforce_collection([
|
316
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com'},
|
317
|
+
{'Id' => '214', 'Name' => 'def', 'Email' => 'def@af.com'}
|
318
|
+
])},
|
319
|
+
{'Id' => '214', 'QuotaId' => '123', 'ClubMembers__r' => build_restforce_collection([
|
320
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com'},
|
321
|
+
{'Id' => '214', 'Name' => 'def', 'Email' => 'def@af.com'}
|
322
|
+
])}
|
323
|
+
])
|
324
|
+
})]
|
325
|
+
allow(client).to receive(:query).once.and_return response
|
326
|
+
account = Quota.includes(prez_clubs: :club_members).find '123'
|
327
|
+
expect(account.prez_clubs).to be_an Array
|
328
|
+
expect(account.prez_clubs.all? { |o| o.is_a? PrezClub }).to eq true
|
329
|
+
expect(account.prez_clubs.first.club_members).to be_an Array
|
330
|
+
expect(account.prez_clubs.first.club_members.all? { |o| o.is_a? ClubMember }).to eq true
|
331
|
+
expect(account.prez_clubs.first.club_members.first.id).to eq '213'
|
332
|
+
expect(account.prez_clubs.first.club_members.first.name).to eq 'abc'
|
333
|
+
expect(account.prez_clubs.first.club_members.first.email).to eq 'abc@af.com'
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
context 'with namespaced sobjects' do
|
338
|
+
it 'formulates the correct SOQL query' do
|
339
|
+
soql = Salesforce::Account.includes({partner_opportunities: :owner}).where(id: '123').to_s
|
340
|
+
expect(soql).to eq <<-SOQL.squish
|
341
|
+
SELECT Id, Business_Partner__c,
|
342
|
+
(SELECT Id, OwnerId, AccountId, Business_Partner__c, Owner.Id
|
343
|
+
FROM Opportunities)
|
344
|
+
FROM Account
|
345
|
+
WHERE (Id = '123')
|
346
|
+
SOQL
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'builds the associated objects and caches them' do
|
350
|
+
response = [build_restforce_sobject({
|
351
|
+
'Id' => '123',
|
352
|
+
'opportunities' => build_restforce_collection([
|
353
|
+
{'Id' => '213', 'AccountId' => '123', 'OwnerId' => '321', 'Business_Partner__c' => '123', 'Owner' => {'Id' => '321'}},
|
354
|
+
{'Id' => '214', 'AccountId' => '123', 'OwnerId' => '321', 'Business_Partner__c' => '123', 'Owner' => {'Id' => '321'}} ])
|
355
|
+
})]
|
356
|
+
allow(client).to receive(:query).once.and_return response
|
357
|
+
account = Salesforce::Account.includes({partner_opportunities: :owner}).find '123'
|
358
|
+
expect(account.partner_opportunities).to be_an Array
|
359
|
+
expect(account.partner_opportunities.all? { |o| o.is_a? Salesforce::Opportunity }).to eq true
|
360
|
+
expect(account.partner_opportunities.first.owner).to be_a Salesforce::User
|
361
|
+
expect(account.partner_opportunities.first.owner.id).to eq '321'
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
context 'an array association nested within a hash association' do
|
366
|
+
it 'formulates the correct SOQL query' do
|
367
|
+
soql = Club.includes(book_clubs: [:club_members, :books]).where(id: '123').to_s
|
368
|
+
expect(soql).to eq <<-SOQL.squish
|
369
|
+
SELECT Id,
|
370
|
+
(SELECT Id, Name, Location,
|
371
|
+
(SELECT Id, Name, Email FROM ClubMembers__r),
|
372
|
+
(SELECT Id, Title, Author FROM Books__r)
|
373
|
+
FROM BookClubs__r)
|
374
|
+
FROM Club__c
|
375
|
+
WHERE (Id = '123')
|
376
|
+
SOQL
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'builds the associated objects and caches them' do
|
380
|
+
response = [build_restforce_sobject({
|
381
|
+
'Id' => '123',
|
382
|
+
'BookClubs__r' => build_restforce_collection([
|
383
|
+
{
|
384
|
+
'Id' => '213',
|
385
|
+
'Name' => 'abc',
|
386
|
+
'Location' => 'abc_location',
|
387
|
+
'ClubMembers__r' => build_restforce_collection([{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com'},{'Id' => '214', 'Name' => 'def', 'Email' => 'def@af.com'}]),
|
388
|
+
'Books__r' => build_restforce_collection([{'Id' => '213', 'Title' => 'Foo', 'Author' => 'author1'},{'Id' => '214', 'Title' => 'Bar', 'Author' => 'author2'}]),
|
389
|
+
},
|
390
|
+
{
|
391
|
+
'Id' => '214',
|
392
|
+
'Name' => 'def',
|
393
|
+
'Location' => 'def_location',
|
394
|
+
'ClubMembers__r' => build_restforce_collection([{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com'},{'Id' => '214', 'Name' => 'def', 'Email' => 'def@af.com'}]),
|
395
|
+
'Books__r' => build_restforce_collection([{'Id' => '213', 'Title' => 'Foo', 'Author' => 'author1'},{'Id' => '214', 'Title' => 'Bar', 'Author' => 'author2'}]),
|
396
|
+
}
|
397
|
+
])
|
398
|
+
})]
|
399
|
+
allow(client).to receive(:query).once.and_return response
|
400
|
+
club = Club.includes(book_clubs: [:club_members, :books]).find(id: '123')
|
401
|
+
expect(club.book_clubs).to be_an Array
|
402
|
+
expect(club.book_clubs.all? { |o| o.is_a? BookClub }).to eq true
|
403
|
+
expect(club.book_clubs.first.name).to eq 'abc'
|
404
|
+
expect(club.book_clubs.first.location).to eq 'abc_location'
|
405
|
+
expect(club.book_clubs.first.club_members).to be_an Array
|
406
|
+
expect(club.book_clubs.first.club_members.all? { |o| o.is_a? ClubMember }).to eq true
|
407
|
+
expect(club.book_clubs.first.club_members.first.id).to eq '213'
|
408
|
+
expect(club.book_clubs.first.club_members.first.name).to eq 'abc'
|
409
|
+
expect(club.book_clubs.first.club_members.first.email).to eq 'abc@af.com'
|
410
|
+
expect(club.book_clubs.first.books).to be_an Array
|
411
|
+
expect(club.book_clubs.first.books.all? { |o| o.is_a? Book }).to eq true
|
412
|
+
expect(club.book_clubs.first.books.first.id).to eq '213'
|
413
|
+
expect(club.book_clubs.first.books.first.title).to eq 'Foo'
|
414
|
+
expect(club.book_clubs.first.books.first.author).to eq 'author1'
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
context 'a hash association nested within a hash association' do
|
419
|
+
it 'formulates the correct SOQL query' do
|
420
|
+
soql = Club.includes(book_clubs: {club_members: :membership}).where(id: '123').to_s
|
421
|
+
expect(soql).to eq <<-SOQL.squish
|
422
|
+
SELECT Id,
|
423
|
+
(SELECT Id, Name, Location,
|
424
|
+
(SELECT Id, Name, Email,
|
425
|
+
(SELECT Id, Type, Club_Member_Id__c FROM Membership__r)
|
426
|
+
FROM ClubMembers__r)
|
427
|
+
FROM BookClubs__r)
|
428
|
+
FROM Club__c
|
429
|
+
WHERE (Id = '123')
|
430
|
+
SOQL
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'builds the associated objects and caches them' do
|
434
|
+
response = [build_restforce_sobject({
|
435
|
+
'Id' => '123',
|
436
|
+
'BookClubs__r' => build_restforce_collection([
|
437
|
+
{
|
438
|
+
'Id' => '213',
|
439
|
+
'Name' => 'abc',
|
440
|
+
'Location' => 'abc_location',
|
441
|
+
'ClubMembers__r' => build_restforce_collection([
|
442
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '111', 'Type' => 'Gold'}])},
|
443
|
+
{'Id' => '214', 'Name' => 'abc', 'Email' => 'abc@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '222', 'Type' => 'Silver'}])},
|
444
|
+
]),
|
445
|
+
},
|
446
|
+
{
|
447
|
+
'Id' => '214',
|
448
|
+
'Name' => 'def',
|
449
|
+
'Location' => 'def_location',
|
450
|
+
'ClubMembers__r' => build_restforce_collection([
|
451
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '111', 'Type' => 'Gold'}])},
|
452
|
+
{'Id' => '214', 'Name' => 'abc', 'Email' => 'abc@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '222', 'Type' => 'Silver'}])},
|
453
|
+
]),
|
454
|
+
}
|
455
|
+
])
|
456
|
+
})]
|
457
|
+
allow(client).to receive(:query).once.and_return response
|
458
|
+
club = Club.includes(book_clubs: {club_members: :membership}).find(id: '123')
|
459
|
+
expect(club.book_clubs).to be_an Array
|
460
|
+
expect(club.book_clubs.all? { |o| o.is_a? BookClub }).to eq true
|
461
|
+
expect(club.book_clubs.first.id).to eq '213'
|
462
|
+
expect(club.book_clubs.first.name).to eq 'abc'
|
463
|
+
expect(club.book_clubs.first.location).to eq 'abc_location'
|
464
|
+
expect(club.book_clubs.first.club_members).to be_an Array
|
465
|
+
expect(club.book_clubs.first.club_members.all? { |o| o.is_a? ClubMember }).to eq true
|
466
|
+
expect(club.book_clubs.first.club_members.first.id).to eq '213'
|
467
|
+
expect(club.book_clubs.first.club_members.first.name).to eq 'abc'
|
468
|
+
expect(club.book_clubs.first.club_members.first.email).to eq 'abc@af.com'
|
469
|
+
expect(club.book_clubs.first.club_members.first.membership).to be_a Membership
|
470
|
+
expect(club.book_clubs.first.club_members.first.membership.id).to eq '111'
|
471
|
+
expect(club.book_clubs.first.club_members.first.membership.type).to eq 'Gold'
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context 'mulitple nested associations' do
|
476
|
+
it 'formulates the correct SOQL query' do
|
477
|
+
soql = Club.includes({prez_clubs: {club_members: :membership}}, {book_clubs: [:club_members, :books]}).where(id: '123').to_s
|
478
|
+
expect(soql).to eq <<-SOQL.squish
|
479
|
+
SELECT Id,
|
480
|
+
(SELECT Id, QuotaId,
|
481
|
+
(SELECT Id, Name, Email,
|
482
|
+
(SELECT Id, Type, Club_Member_Id__c FROM Membership__r)
|
483
|
+
FROM ClubMembers__r)
|
484
|
+
FROM PrezClubs__r),
|
485
|
+
(SELECT Id, Name, Location,
|
486
|
+
(SELECT Id, Name, Email FROM ClubMembers__r),
|
487
|
+
(SELECT Id, Title, Author FROM Books__r)
|
488
|
+
FROM BookClubs__r)
|
489
|
+
FROM Club__c
|
490
|
+
WHERE (Id = '123')
|
491
|
+
SOQL
|
492
|
+
end
|
493
|
+
|
494
|
+
it 'builds the associated objects and caches them' do
|
495
|
+
response = [build_restforce_sobject({
|
496
|
+
'Id' => '123',
|
497
|
+
'PrezClubs__r' => build_restforce_collection([
|
498
|
+
{'Id' => '213', 'QuotaId' => '123', 'ClubMembers__r' => build_restforce_collection([
|
499
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '111', 'Type' => 'Gold'}])},
|
500
|
+
{'Id' => '214', 'Name' => 'def', 'Email' => 'def@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '222', 'Type' => 'Silver'}])},
|
501
|
+
])},
|
502
|
+
{'Id' => '214', 'QuotaId' => '123', 'ClubMembers__r' => build_restforce_collection([
|
503
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '111', 'Type' => 'Gold'}])},
|
504
|
+
{'Id' => '214', 'Name' => 'def', 'Email' => 'def@af.com', 'Membership__r' => build_restforce_collection([{'Id' => '222', 'Type' => 'Silver'}])},
|
505
|
+
])}
|
506
|
+
]),
|
507
|
+
'BookClubs__r' => build_restforce_collection([
|
508
|
+
{
|
509
|
+
'Id' => '213',
|
510
|
+
'Name' => 'abc',
|
511
|
+
'Location' => 'abc_location',
|
512
|
+
'ClubMembers__r' => build_restforce_collection([
|
513
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com'},
|
514
|
+
{'Id' => '214', 'Name' => 'abc', 'Email' => 'abc@af.com'},
|
515
|
+
]),
|
516
|
+
'Books__r' => build_restforce_collection([
|
517
|
+
{'Id' => '213', 'Title' => 'Foo', 'Author' => 'author1'},
|
518
|
+
{'Id' => '214', 'Title' => 'Bar', 'Author' => 'author2'},
|
519
|
+
])
|
520
|
+
},
|
521
|
+
{
|
522
|
+
'Id' => '214',
|
523
|
+
'Name' => 'def',
|
524
|
+
'Location' => 'def_location',
|
525
|
+
'ClubMembers__r' => build_restforce_collection([
|
526
|
+
{'Id' => '213', 'Name' => 'abc', 'Email' => 'abc@af.com'},
|
527
|
+
{'Id' => '214', 'Name' => 'abc', 'Email' => 'abc@af.com'},
|
528
|
+
]),
|
529
|
+
'Books__r' => build_restforce_collection([
|
530
|
+
{'Id' => '213', 'Title' => 'Foo', 'Author' => 'author1'},
|
531
|
+
{'Id' => '214', 'Title' => 'Bar', 'Author' => 'author2'},
|
532
|
+
])
|
533
|
+
}
|
534
|
+
])
|
535
|
+
})]
|
536
|
+
allow(client).to receive(:query).once.and_return response
|
537
|
+
club = Club.includes({prez_clubs: {club_members: :membership}}, {book_clubs: [:club_members, :books]}).find(id: '123')
|
538
|
+
expect(club.prez_clubs).to be_an Array
|
539
|
+
expect(club.prez_clubs.all? { |o| o.is_a? PrezClub }).to eq true
|
540
|
+
expect(club.prez_clubs.first.club_members).to be_an Array
|
541
|
+
expect(club.prez_clubs.first.club_members.all? { |o| o.is_a? ClubMember }).to eq true
|
542
|
+
expect(club.prez_clubs.first.club_members.first.id).to eq '213'
|
543
|
+
expect(club.prez_clubs.first.club_members.first.name).to eq 'abc'
|
544
|
+
expect(club.prez_clubs.first.club_members.first.email).to eq 'abc@af.com'
|
545
|
+
expect(club.prez_clubs.first.club_members.first.membership).to be_a Membership
|
546
|
+
expect(club.prez_clubs.first.club_members.first.membership.id).to eq '111'
|
547
|
+
expect(club.prez_clubs.first.club_members.first.membership.type).to eq 'Gold'
|
548
|
+
expect(club.book_clubs).to be_an Array
|
549
|
+
expect(club.book_clubs.all? { |o| o.is_a? BookClub }).to eq true
|
550
|
+
expect(club.book_clubs.first.id).to eq '213'
|
551
|
+
expect(club.book_clubs.first.name).to eq 'abc'
|
552
|
+
expect(club.book_clubs.first.location).to eq 'abc_location'
|
553
|
+
expect(club.book_clubs.first.club_members).to be_an Array
|
554
|
+
expect(club.book_clubs.first.club_members.all? { |o| o.is_a? ClubMember }).to eq true
|
555
|
+
expect(club.book_clubs.first.club_members.first.id).to eq '213'
|
556
|
+
expect(club.book_clubs.first.club_members.first.name).to eq 'abc'
|
557
|
+
expect(club.book_clubs.first.club_members.first.email).to eq 'abc@af.com'
|
558
|
+
expect(club.book_clubs.first.books).to be_an Array
|
559
|
+
expect(club.book_clubs.first.books.all? { |o| o.is_a? Book }).to eq true
|
560
|
+
expect(club.book_clubs.first.books.first.id).to eq '213'
|
561
|
+
expect(club.book_clubs.first.books.first.title).to eq 'Foo'
|
562
|
+
expect(club.book_clubs.first.books.first.author).to eq 'author1'
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
context 'nested belongs-to association' do
|
567
|
+
it 'formulates the correct SOQL query' do
|
568
|
+
soql = Comment.includes(post: :blog).where(id: '123').to_s
|
569
|
+
expect(soql).to eq <<-SOQL.squish
|
570
|
+
SELECT Id, PostId, PosterId__c, FancyPostId, Body__c,
|
571
|
+
PostId.Id, PostId.Title__c, PostId.BlogId,
|
572
|
+
PostId.BlogId.Id, PostId.BlogId.Name, PostId.BlogId.Link__c
|
573
|
+
FROM Comment__c
|
574
|
+
WHERE (Id = '123')
|
575
|
+
SOQL
|
576
|
+
end
|
577
|
+
|
578
|
+
it 'builds the associated objects and caches them' do
|
579
|
+
response = [build_restforce_sobject({
|
580
|
+
'Id' => '123',
|
581
|
+
'PostId' => '321',
|
582
|
+
'PosterId__c' => '432',
|
583
|
+
'FancyPostId' => '543',
|
584
|
+
'Body__c' => 'body',
|
585
|
+
'PostId' => {
|
586
|
+
'Id' => '321',
|
587
|
+
'Title__c' => 'title',
|
588
|
+
'BlogId' => '432',
|
589
|
+
'BlogId' => {
|
590
|
+
'Id' => '432',
|
591
|
+
'Name' => 'name',
|
592
|
+
'Link__c' => 'link'
|
593
|
+
}
|
594
|
+
}
|
595
|
+
})]
|
596
|
+
allow(client).to receive(:query).once.and_return response
|
597
|
+
comment = Comment.includes(post: :blog).find '123'
|
598
|
+
expect(comment.post).to be_a Post
|
599
|
+
expect(comment.post.id).to eq '321'
|
600
|
+
expect(comment.post.title).to eq 'title'
|
601
|
+
expect(comment.post.blog).to be_a Blog
|
602
|
+
expect(comment.post.blog.id).to eq '432'
|
603
|
+
expect(comment.post.blog.name).to eq 'name'
|
604
|
+
expect(comment.post.blog.link).to eq 'link'
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
608
|
+
context 'when invalid nested associations are passed' do
|
609
|
+
it 'raises an error' do
|
610
|
+
expect { Quota.includes(prez_clubs: :invalid).find('123') }.to raise_error(ActiveForce::Association::InvalidAssociationError, 'Association named invalid was not found on PrezClub')
|
611
|
+
end
|
612
|
+
end
|
288
613
|
end
|
289
614
|
end
|
290
615
|
end
|
@@ -96,6 +96,20 @@ describe ActiveForce::SObject do
|
|
96
96
|
it 'sets percent field upon object instantiation' do
|
97
97
|
expect(subject.new(**instantiation_attributes)[:percent]).to eq(percent)
|
98
98
|
end
|
99
|
+
|
100
|
+
context 'when the override to default value is the same as the default value' do
|
101
|
+
let(:percent) { 50.0 }
|
102
|
+
|
103
|
+
it 'sends percent to salesforce' do
|
104
|
+
expect(client).to receive(:create!)
|
105
|
+
.with(anything, hash_including('Percent_Label' => percent))
|
106
|
+
subject.create(**instantiation_attributes)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'sets percent field upon object instantiation' do
|
110
|
+
expect(subject.new(**instantiation_attributes)[:percent]).to eq(percent)
|
111
|
+
end
|
112
|
+
end
|
99
113
|
end
|
100
114
|
end
|
101
115
|
|
@@ -301,18 +315,67 @@ describe ActiveForce::SObject do
|
|
301
315
|
end
|
302
316
|
end
|
303
317
|
|
304
|
-
describe
|
305
|
-
let(:
|
318
|
+
describe '.count' do
|
319
|
+
let(:response) { [Restforce::Mash.new(expr0: 1)] }
|
320
|
+
|
321
|
+
before do
|
322
|
+
allow(client).to receive(:query).and_return(response)
|
323
|
+
end
|
306
324
|
|
307
|
-
it
|
308
|
-
|
325
|
+
it 'sends the correct query to the client' do
|
326
|
+
expected = 'SELECT count(Id) FROM Whizbang__c'
|
327
|
+
Whizbang.count
|
328
|
+
expect(client).to have_received(:query).with(expected)
|
309
329
|
end
|
310
330
|
|
311
|
-
it
|
312
|
-
expect(client).to receive(:query).and_return(count_response)
|
331
|
+
it 'returns the result from the response' do
|
313
332
|
expect(Whizbang.count).to eq(1)
|
314
333
|
end
|
315
334
|
|
335
|
+
it 'works with .where' do
|
336
|
+
expected = 'SELECT count(Id) FROM Whizbang__c WHERE (Boolean_Label = true)'
|
337
|
+
Whizbang.where(boolean: true).count
|
338
|
+
expect(client).to have_received(:query).with(expected)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
describe '.sum' do
|
343
|
+
let(:response) { [Restforce::Mash.new(expr0: 22)] }
|
344
|
+
|
345
|
+
before do
|
346
|
+
allow(client).to receive(:query).and_return(response)
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'raises ArgumentError if given blank' do
|
350
|
+
expect { Whizbang.sum(nil) }.to raise_error(ArgumentError, 'field is required')
|
351
|
+
end
|
352
|
+
|
353
|
+
it 'raises ArgumentError if given invalid field' do
|
354
|
+
expect { Whizbang.sum(:invalid) }
|
355
|
+
.to raise_error(ArgumentError, /field 'invalid' does not exist on Whizbang/i)
|
356
|
+
end
|
357
|
+
|
358
|
+
it 'sends the correct query to the client' do
|
359
|
+
expected = 'SELECT sum(Percent_Label) FROM Whizbang__c'
|
360
|
+
Whizbang.sum(:percent)
|
361
|
+
expect(client).to have_received(:query).with(expected)
|
362
|
+
end
|
363
|
+
|
364
|
+
it 'works when given a string field' do
|
365
|
+
expected = 'SELECT sum(Percent_Label) FROM Whizbang__c'
|
366
|
+
Whizbang.sum('percent')
|
367
|
+
expect(client).to have_received(:query).with(expected)
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'returns the result from the response' do
|
371
|
+
expect(Whizbang.sum(:percent)).to eq(22)
|
372
|
+
end
|
373
|
+
|
374
|
+
it 'works with .where' do
|
375
|
+
expected = 'SELECT sum(Percent_Label) FROM Whizbang__c WHERE (Boolean_Label = true)'
|
376
|
+
Whizbang.where(boolean: true).sum(:percent)
|
377
|
+
expect(client).to have_received(:query).with(expected)
|
378
|
+
end
|
316
379
|
end
|
317
380
|
|
318
381
|
describe "#find_by" do
|
data/spec/support/sobjects.rb
CHANGED
@@ -10,6 +10,7 @@ end
|
|
10
10
|
class Post < ActiveForce::SObject
|
11
11
|
self.table_name = "Post__c"
|
12
12
|
field :title
|
13
|
+
field :blog_id, from: "BlogId"
|
13
14
|
has_many :comments
|
14
15
|
has_many :impossible_comments, model: Comment, scoped_as: ->{ where('1 = 0') }
|
15
16
|
has_many :reply_comments, model: Comment, scoped_as: ->(post){ where(body: "RE: #{post.title}").order('CreationDate DESC') }
|
@@ -17,6 +18,13 @@ class Post < ActiveForce::SObject
|
|
17
18
|
has_many :poster_comments, { foreign_key: :poster_id, model: Comment }
|
18
19
|
has_one :last_comment, model: Comment, scoped_as: -> { where.not(body: nil).order('CreatedDate DESC') }
|
19
20
|
has_one :repeat_comment, model: Comment, scoped_as: ->(post) { where(body: post.title) }
|
21
|
+
belongs_to :blog
|
22
|
+
end
|
23
|
+
|
24
|
+
class Blog < ActiveForce::SObject
|
25
|
+
field :name, from: 'Name'
|
26
|
+
field :link, from: 'Link__c'
|
27
|
+
has_many :posts
|
20
28
|
end
|
21
29
|
class Territory < ActiveForce::SObject
|
22
30
|
field :quota_id, from: "Quota__c"
|
@@ -26,7 +34,40 @@ end
|
|
26
34
|
class PrezClub < ActiveForce::SObject
|
27
35
|
field :quota_id, from: 'QuotaId'
|
28
36
|
belongs_to :quota
|
37
|
+
has_many :club_members
|
38
|
+
has_one :club_owner
|
39
|
+
end
|
40
|
+
|
41
|
+
class Club < ActiveForce::SObject
|
42
|
+
has_many :book_clubs
|
43
|
+
has_many :prez_clubs
|
44
|
+
end
|
45
|
+
|
46
|
+
class BookClub < ActiveForce::SObject
|
47
|
+
field :name, from: 'Name'
|
48
|
+
field :location, from: 'Location'
|
49
|
+
has_many :club_members
|
50
|
+
has_many :books
|
29
51
|
end
|
52
|
+
class ClubMember < ActiveForce::SObject
|
53
|
+
field :name, from: 'Name'
|
54
|
+
field :email, from: 'Email'
|
55
|
+
has_one :membership
|
56
|
+
end
|
57
|
+
|
58
|
+
class Book < ActiveForce::SObject
|
59
|
+
field :title, from: 'Title'
|
60
|
+
field :author, from: 'Author'
|
61
|
+
end
|
62
|
+
class Membership < ActiveForce::SObject
|
63
|
+
field :type, from: 'Type'
|
64
|
+
field :club_member_id, from: 'Club_Member_Id__c'
|
65
|
+
end
|
66
|
+
|
67
|
+
class ClubOwner < ActiveForce::SObject
|
68
|
+
field :name, from: 'Name'
|
69
|
+
end
|
70
|
+
|
30
71
|
class Quota < ActiveForce::SObject
|
31
72
|
field :id, from: 'Bar_Id__c'
|
32
73
|
has_many :prez_clubs
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_force
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eloy Espinaco
|
8
8
|
- Pablo Oldani
|
9
9
|
- Armando Andini
|
10
10
|
- José Piccioni
|
11
|
-
autorequire:
|
11
|
+
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2023-
|
14
|
+
date: 2023-08-23 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activemodel
|
@@ -150,6 +150,7 @@ files:
|
|
150
150
|
- lib/active_force/association.rb
|
151
151
|
- lib/active_force/association/association.rb
|
152
152
|
- lib/active_force/association/belongs_to_association.rb
|
153
|
+
- lib/active_force/association/eager_load_builder_for_nested_includes.rb
|
153
154
|
- lib/active_force/association/eager_load_projection_builder.rb
|
154
155
|
- lib/active_force/association/has_many_association.rb
|
155
156
|
- lib/active_force/association/has_one_association.rb
|
@@ -192,7 +193,7 @@ metadata:
|
|
192
193
|
bug_tracker_uri: https://github.com/Beyond-Finance/active_force/issues
|
193
194
|
changelog_uri: https://github.com/Beyond-Finance/active_force/blob/main/CHANGELOG.md
|
194
195
|
source_code_uri: https://github.com/Beyond-Finance/active_force
|
195
|
-
post_install_message:
|
196
|
+
post_install_message:
|
196
197
|
rdoc_options: []
|
197
198
|
require_paths:
|
198
199
|
- lib
|
@@ -207,8 +208,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
208
|
- !ruby/object:Gem::Version
|
208
209
|
version: '0'
|
209
210
|
requirements: []
|
210
|
-
rubygems_version: 3.
|
211
|
-
signing_key:
|
211
|
+
rubygems_version: 3.1.6
|
212
|
+
signing_key:
|
212
213
|
specification_version: 4
|
213
214
|
summary: Help you implement models persisting on Sales Force within Rails using RESTForce
|
214
215
|
test_files:
|