Presented by Scott Covert / @scottbcovert
Umm, my workflow rule can't do that-what should I do?
The world of Apex development ain't all sunshine and rainbows.
Should my logic live in a before or after trigger?
Null reference? I thought all records have ids?
Umm, you mean you want to insert more than a single account at once?
...what's a governor limit?
Unit tests?
...but it's sorta working
Before:
After:
Insert:
Update:
trigger accountTestTrggr on Account (before insert, before update) {
//This only handles the first record in the Trigger.new collection
//But if more than 1 Account initiated this trigger, those additional records
//will not be processed
Account acct = Trigger.new[0];
List<Contact> contacts = [select id, salutation, firstname, lastname, email
from Contact where accountId = :acct.Id];
}
trigger accountTestTrggr on Account (before insert, before update) {
List<String> accountNames = new List<String>{};
//Loop through all records in the Trigger.new collection
for(Account a: Trigger.new){
//Concatenate the Name and billingState into the Description field
a.Description = a.Name + ':' + a.BillingState
}
}
.
trigger accountTestTrggr on Account (before insert, before update) {
//For loop to iterate through all the incoming Account records
for(Account a: Trigger.new){
/*
THIS FOLLOWING QUERY IS INEFFICIENT AND DOESN'T SCALE
Since the SOQL Query for related Contacts is within the FOR loop, if this trigger is initiated
with more than 20 records, the trigger will exceed the trigger governor limit
of maximum 20 SOQL Queries.
*/
List<Contact> contacts = [select id, salutation, firstname, lastname, email
from Contact where accountId = :a.Id];
for(Contact c: contacts){
System.debug('Contact Id[' + c.Id + '], FirstName[' + c.firstname + '],
LastName[' + c.lastname +']');
c.Description=c.salutation + ' ' + c.firstName + ' ' + c.lastname;
/*
THIS FOLLOWING DML STATEMENT IS INEFFICIENT AND DOESN'T SCALE
Since the UPDATE dml operation is within the FOR loop, if this trigger is initiated
with more than 20 records, the trigger will exceed the trigger governor limit
of maximum 20 DML Operations.
*/
update c;
}
}
}
trigger accountTestTrggr on Account (before insert, before update) {
//This queries all Contacts related to the incoming Account records in a single SOQL query.
//This is also an example of how to use child relationships in SOQL
List<Account> accountsWithContacts = [select id, name, (select id, salutation, description,
firstname, lastname, email from Contacts)
from Account where Id IN :Trigger.newMap.keySet()];
List<Contact> contactsToUpdate = new List<Contact>{};
// For loop to iterate through all the queried Account records
for(Account a: accountsWithContacts){
// Use the child relationships dot syntax to access the related Contacts
for(Contact c: a.Contacts){
System.debug('Contact Id[' + c.Id + '], FirstName[' + c.firstname + '], LastName[' + c.lastname +']');
c.Description=c.salutation + ' ' + c.firstName + ' ' + c.lastname;
contactsToUpdate.add(c);
}
}
//Now outside the FOR Loop, perform a single Update DML statement.
update contactsToUpdate;
}
Makes unit testing much easier
Keeps your codebase DRY
trigger updateContactOtherAddress on Account(after insert, after update) {
if (trigger.isUpdate) {
//Identify Account Address Changes
Set<Id> setAccountAddressChangedIds = new Set<Id>();
for (Account oAccount : trigger.new) {
Account oOldAccount = trigger.oldMap.get(oAccount.Id);
boolean bIsChanged = (oAccount.BillingStreet != oOldAccount.BillingStreet || oAccount.BillingCity != oOldAccount.BillingCity);
if (bIsChanged) {
setAccountAddressChangedIds.add(oAccount.Id);
}
}
//If any, get contacts associated with each account
if (setAccountAddressChangedIds.isEmpty() == false) {
List<Contact> listContacts = [SELECT Id, AccountId FROM Contact WHERE AccountId IN :setAccountAddressChangedIds];
for (Contact oContact : listContacts) {
//Get Account
oAccount = trigger.newMap.get(oContact.AccountId);
//Set Address
oContact.OtherStreet = oAccount.BillingStreet;
oContact.OtherCity = oAccount.BillingCity;
oContact.OtherState = oAccount.BillingState;
oContact.OtherPostalCode = oAccount.BillingPostalCode;
}
//If any, execute DML command to save contact addresses
if (listContacts.isEmpty() == false) {
update listContacts;
}
}
}
}
trigger AccountBeforeEventListener on Account (before insert, before update) {
if (trigger.isInsert) {
AccountUtil.setDefaultValues(trigger.new);
AccountUtil.setIndustryCode(trigger.new);
}
}
public class AccountUtil {
public static void setDefaultValues(List<Account> listAccounts) {
for (Account oAccount : listAccounts) {
if (oAccount.Industry == null) {
oAccount.Industry = ‘Cloud Computing’;
}
}
}
public static void setIndustryCode(List<Account> listAccounts) {
for (Account oAccount : listAccounts) {
if (oAccount.Industry == ‘Cloud Computing’) {
oAccount.Industry_Code__c = ‘CC’;
}
}
}
}
No more: