active_force 0.15.1 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|