Generic sObjects - Setting Fields
Not Started

We solved a really interesting problem in the last lesson. Let's look at another:

public void clearAddresses(List<Account> accounts, List<Contact> contacts){ for(Account acc : accounts){ acc.BillingCountry = null; acc.BillingState = null; acc.BillingCity = null; acc.BillingStreet = null; acc.BillingPostalCode = null; } for(Contact con : contacts){ acc.MailingCountry = null; acc.MailingState = null; acc.MailingCity = null; acc.MailingStreet = null; acc.MailingPostalCode = null; } }

This method accepts a list of accounts and contacts, and it iterates through each record to clear out the address fields. However, we may receive a new requirement to perform the same action on Lead or other sObjects in our organization. To address this without explicit code for each sObject, we can leverage abstractions using the sObject datatype once again for a generic and reusable solution.

To accomplish this, we can utilize the put() instance method from the sObject class. When calling this method, we provide two parameters. The first parameter is the API name of the field to set, which can be either a String or a Schema field token. The second parameter represents the value to assign to the field.

Contact c = new Contact(); c.put('FirstName', 'Max'); c.put('LastName', 'Arloson');

or in our case, to blank out the field we'll need:

c.put('FirstName', null); c.put('LastName', null);

We'll need a nested for loop to make this work. The plan is to create a new method that accepts List<sObject> and List<String> representing the fields to blank out. We'll iterate through each sObject in the list and, for each iteration, we'll loop through the list of fields. Within this inner for loop, we'll call the put() method to clear the respective field.

public void clearFields(List<sObject> records, List<String> fields){ for(sObject obj : records){ // this outer loop is responsible for looping through the sObjects for(String field : fields){ // the inner loop is responsible for iterating over each field obj.put(field, null); // this line executes once for each field for each obj. So, if we pass in a list of 5 objects and a list of 5 fields, this line executes 25 times } } }

Notice that there is no casting required this time! The caller looks like this:

public void clearAddresses(List<Account> accounts, List<Contact> contacts){ List<String> accountFieldsToClear = new List<String>{'BillingCountry', 'BillingState', 'BillingCity', 'BillingStreet', 'BillingPostalCode'}; List<String> contactFieldsToClear = new List<String>{'MailingCountry', 'MailingState', 'MailingCity', 'MailingStreet', 'MailingPostalCode'}; clearFields(accounts, accountFieldsToClear); clearFields(contacts, contactFieldsToClear); }

Perfect! With this approach, if additional fields need to be included or existing fields need to be removed, we can simply update the list of fields without having to add new lines of code. Similarly, if there is a requirement to clear fields on other sObjects, we can achieve that without code duplication. This allows for easier maintenance and scalability of the codebase.

That's all for this course! We can start seeing some of the advantages Apex has over Flow when we consider generics. If you're interested in more, check out the OOP courses where we create our own abstractions.

If you are hungry for more sObject content let me know. Otherwise, check out the additional capabilities on sObjects from the Apex Developer Guide.

Challenge

The setDefaultValue method accepts three parameters. The caller will provide a list of sObject records whose provided fields must be set to the provided default value. You must iterate through each sObject and set the provided default value for each field. Here's an example of what the caller may look like:

Opportunity o1 = new Opportunity(Amount = 2200, Probability=50); Opportunity o2 = new Opportunity(Amount = 3000, Probability=45); List<Opportunity> opportunities = new List<Opportunity>{o1, o2}; List<String> fieldsToDefault = new List<String>{'Amount', 'Probability'}; sObjectUtils sUtils = new sObjectUtils(); sUtils.setDefaultValue(opportunities, fieldsToDefault, 0); // o1.Amount and o1.Probability are now 0 // o2.Amount and o2.Probability are now 0 sUtils.setDefaultValue(opportunities, fieldsToDefault, 100); // o1.Amount and o1.Probability are now 100 // o2.Amount and o2.Probability are now 100