Skip to content

Commit 5dd5969

Browse files
authored
Added comments & example methods for using Schema.SObjectField & overloaded methods (#2)
* Added comments to QueryGenerator about the design & implementation * Cleaned up some w h it e s p a c e * Added methods that use a Schema.SObjectField to indicate a code dependency while still using strings * Add some overloaded & related methods to demonstrate the recommended implementation
1 parent 11b0304 commit 5dd5969

File tree

4 files changed

+140
-9
lines changed

4 files changed

+140
-9
lines changed

src/classes/LeadQueryRepository.cls

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,47 @@ public class LeadQueryRepository {
33
// Each SObject should have its own repository class that contains methods for commonly used queries
44
// Each method can use a different field set to generate the query fields,
55
// or you can use 1 field set for all methods - tweak the code to fit your use case
6+
7+
// One of the most common use cases is querying for a record or list of records by ID(s)
8+
// The simplest way is to have some overloaded methods with self-descriptive names
9+
// The methods then use your desired field set to generate & execute the query
610
public static Lead getLeadById(Id leadId) {
11+
return getLeadsById(new Set<Id>{leadId})[0];
12+
}
13+
14+
public static List<Lead> getLeadsById(List<Lead> leadList) {
15+
return getLeadsById(new Map<Id, Lead>(leadList).keySet());
16+
}
17+
18+
public static List<Lead> getLeadsById(List<Id> leadIdSet) {
19+
return getLeadsById(new Set<Id>(leadIdSet));
20+
}
21+
22+
public static List<Lead> getLeadsById(Map<Id, Lead> leadMap) {
23+
return getLeadsById(leadMap.keySet());
24+
}
25+
26+
public static List<Lead> getLeadsById(Set<Id> leadIdSet) {
727
// Created a string for your where clause
8-
String whereClause = 'WHERE Id = :leadId';
28+
String whereClause = 'WHERE ' + Schema.Lead.Id + ' IN :leadIdSet';
929
// Created a new instance of QueryGenerator, using a field set and your where clause
1030
String query = new QueryGenerator(SObjectType.Lead.FieldSets.MyFieldSet).buildQuery(whereClause);
1131

1232
// Database.query returns generic SObjects, so cast it to the desired SObject type & return it
13-
return (Lead)Database.query(query);
33+
return (List<Lead>)Database.query(query);
1434
}
1535

36+
// Another common use case is to query for status (or list of statuses) or similar field (like opportunity stage)
37+
// These methods can all be placed into the same query repository class, or you could further break things down
38+
// into multiple classes for the same SObjectType. Adapt to your use cases, but keep it simple
1639
public static List<Lead> getLeadsByStatus(String status) {
17-
// Created a string for your where clause
18-
String whereClause = 'WHERE Status = :status';
19-
// Created a new instance of QueryGenerator, using a field set and your where clause
40+
return getLeadsByStatuses(new List<String>{status});
41+
}
42+
43+
public static List<Lead> getLeadsByStatuses(List<String> statuses) {
44+
String whereClause = 'WHERE ' + Schema.Lead.Status + ' IN :statuses';
2045
String query = new QueryGenerator(SObjectType.Lead.FieldSets.MyFieldSet).buildQuery(whereClause);
2146

22-
// Database.query returns generic SObjects, so cast it to the desired SObject type & return it
2347
return (List<Lead>)Database.query(query);
2448
}
2549

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
@isTest
2+
private class LeadQueryRepositoryTest {
3+
4+
@testSetup
5+
static void setup() {
6+
List<Lead> leadList = new List<Lead>();
7+
for(Integer i = 0; i < 5; i++) {
8+
Lead lead = new Lead(
9+
Company = 'My Test Company',
10+
LastName = 'Gillespie'
11+
);
12+
leadList.add(lead);
13+
}
14+
insert leadList;
15+
}
16+
17+
@isTest
18+
static void getLeadById_Test() {
19+
Lead expectedLead = [SELECT Id FROM Lead LIMIT 1];
20+
21+
Test.startTest();
22+
23+
Lead returnedLead = LeadQueryRepository.getLeadById(expectedLead.Id);
24+
25+
Test.stopTest();
26+
}
27+
28+
@isTest
29+
static void getLeadsById_WHEN_parameterIsAListOfIds() {
30+
List<Lead> expectedLeads = [SELECT Id FROM Lead];
31+
List<Id> expectedLeadIdList = new List<Id>(new Map<Id, Lead>(expectedLeads).keySet());
32+
33+
Test.startTest();
34+
35+
List<Lead> returnedLeadList = LeadQueryRepository.getLeadsById(expectedLeadIdList);
36+
37+
Test.stopTest();
38+
}
39+
40+
@isTest
41+
static void getLeadsById_WHEN_parameterIsAListOfRecords() {
42+
List<Lead> expectedLeadList = [SELECT Id FROM Lead];
43+
44+
Test.startTest();
45+
46+
List<Lead> returnedLeads = LeadQueryRepository.getLeadsById(expectedLeadList);
47+
48+
Test.stopTest();
49+
}
50+
51+
@isTest
52+
static void getLeadsById_WHEN_parameterIsAMap() {
53+
Map<Id, Lead> expectedLeadMap = new Map<Id, Lead>([SELECT Id FROM Lead]);
54+
55+
Test.startTest();
56+
57+
List<Lead> returnedLeads = LeadQueryRepository.getLeadsById(expectedLeadMap);
58+
59+
Test.stopTest();
60+
}
61+
62+
@isTest
63+
static void getLeadsById_WHEN_parameterIsASetOfIds() {
64+
Set<Id> expectedLeadIdSet = new Map<Id, Lead>([SELECT Id FROM Lead]).keySet();
65+
66+
Test.startTest();
67+
68+
List<Lead> returnedLeadList = LeadQueryRepository.getLeadsById(expectedLeadIdSet);
69+
70+
Test.stopTest();
71+
}
72+
73+
@isTest
74+
static void getLeadsByStatus() {
75+
Lead lead = [SELECT Id, Status FROM Lead LIMIT 1];
76+
77+
Test.startTest();
78+
79+
List<Lead> returnedLeadList = LeadQueryRepository.getLeadsByStatus(lead.Status);
80+
81+
Test.stopTest();
82+
}
83+
84+
@isTest
85+
static void getLeadsByStatuses() {
86+
Lead lead = [SELECT Id, Status FROM Lead LIMIT 1];
87+
List<String> leadStatusList = new List<String>{lead.Status};
88+
89+
Test.startTest();
90+
91+
List<Lead> returnedLeadList = LeadQueryRepository.getLeadsByStatuses(leadStatusList);
92+
93+
Test.stopTest();
94+
}
95+
96+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3+
<apiVersion>38.0</apiVersion>
4+
<status>Active</status>
5+
</ApexClass>

src/classes/QueryGenerator.cls

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
public class QueryGenerator {
22

3+
// Each query repository class will have one or more methods that handle generating a query
4+
// This class handles taking a fieldSet and an optional string for a WHERE statement
5+
// Everything is parsed and a query string is returned to the originating query repository class
6+
// The query repository should handle executing the query so that any relevant variables are in scope
7+
// Finally, it should cast the SObjects to the appropriate SObjectType
8+
39
private Schema.FieldSet fieldSet;
410
private SObjectType sobjectType;
511
private Set<String> queryFields;
612

713
public QueryGenerator(Schema.FieldSet fieldSet) {
8-
this.fieldSet = fieldSet;
14+
this.fieldSet = fieldSet;
915

10-
this.sobjectType = fieldSet.getSObjectType();
11-
this.queryFields = new Set<String>{'Id'}; // Always add the ID field, just in case it's not in the field set
16+
this.sobjectType = fieldSet.getSObjectType();
17+
this.queryFields = new Set<String>{'Id'}; // Always add the ID field, just in case it's not in the field set
1218

1319
this.parseFieldSetMembers();
1420
}

0 commit comments

Comments
 (0)