Apex Trigger Status Made Simple
Have you ever needed to deactivate a trigger for some maintenance activities on records or for a code deployment?
At a high level, the act of activating/deactivating a trigger is simple. Go to your Salesforce sandbox, modify the status of the trigger and deploy the code. Depending on your unit test coverage for the trigger you may have to tweak the test class and include that in the deployment.
If you're working in a Salesforce organization that has lots of code then the deployment may take some time. 20 minutes. 40 minutes. Maybe more.
What if you could simply check/uncheck a box in order to turn on/off a trigger?
The solution I am going to illustrate here allows for very simple and quick manipulation of trigger status via Custom Setting. At a high level, the trigger will look for its own status record in a Custom Setting object and based upon that designation the trigger will either process its logic or it won't.
The first thing we need to make this work is a Custom Setting object. Setup > Develop > Custom Settings > New. Details of the new object are:
We will need to setup one custom field for this new object:
Make sure you have a corresponding trigger record in the Custom Setting object. Navigate to the Custom Setting object within Salesforce setup, click the Manage button then the New button:
Now we need our trigger. In this case, we will use a Contact trigger and a trigger handler. The simplified trigger is as follows:
/*
Created by: Greg Hacic
Last Update: 30 July 2015 by Greg Hacic
Questions?: greg@interactiveties.com
Notes:
- tests located at contactTriggerTest.cls
*/
trigger contactTrigger on Contact(after insert) {
contactTriggerHandler handler = new contactTriggerHandler(); //construct the trigger handler
if (Trigger.IsInsert && Trigger.isAfter) { //after insert
handler.OnAfterInsert(Trigger.new); //pass the new List of records to the handler for processing
}
}
The handler will be where we grab the trigger status from the Custom Setting.
/*
Created by: Greg Hacic
Last Update: 30 July 2015 by Greg Hacic
Questions?: greg@interactiveties.com
Notes:
- tests located at contactTriggerTest.cls
*/
public class contactTriggerHandler {
public void OnAfterInsert(List<Contact> newRecords) {
if (isOkayToRun) { //if it is okay to run the trigger
contactAfterInsertLogic(newRecords); //pass the List of new records to the contactAfterInsertLogic for processing
}
}
//determines whether or not the trigger logic is okay to run
public static Boolean isOkayToRun {
//getter constructor
get {
Boolean returnBoolean = true; //default the boolean return value to true - this is done to make sure the trigger fires when the developer fails to create a corresponding Custom Setting record
Trigger_Status__c t = Trigger_Status__c.getInstance('contactTrigger'); //grab the Trigger_Status__c custom setting object record named contactTrigger
if (t != null) { //if there was a record found
returnBoolean = t.Status__c; //set the returnBoolean value to the Status__c boolean value for the found record
}
return returnBoolean; //return the boolean value
}
}
//method for processing of actual business logic related to the trigger
private void contactAfterInsertLogic(List<Contact> newRecords) {
for (Contact c : newRecords) { //for all records
//do something here
}
}
}
As you can see we grab the trigger status from the Custom Setting when the trigger handler is constructed. Since the information is stored in a Custom Setting we can easily and efficiently access it using the isOkayToRun getter method.
Make sure you use the same Name from your Custom Setting on line 22 within the trigger handler. Otherwise, the handler will not find a matching record in the Custom Setting object.
Apex code is no good without unit tests...
/*
Created by: Greg Hacic
Last Update: 30 July 2015 by Greg Hacic
Questions?: greg@interactiveties.com
Notes:
- tests contactTrigger.trigger (100.00% coverage)
- tests contactTriggerHandler.cls (100.00% coverage)
*/
@isTest
private class contactTriggerTest {
//tests contactTrigger.trigger & contactTriggerHandler.cls
@isTest //defines method for use during testing only
static void triggerLogic() {
//create some Trigger_Status__c records
List<Trigger_Status__c> triggerStatus = new List<Trigger_Status__c>();
triggerStatus.add(new Trigger_Status__c(Name = 'contactTrigger', Status__c = true));
insert triggerStatus;
//create some accounts
List<Account> accounts = new List<Account>();
accounts.add(new Account(Name = 'Tess Is My Dog LLC'));
insert accounts;
Test.startTest(); //denote testing context
//create a Contact
List<Contact> contacts = new List<Contact>();
contacts.add(new Contact(AccountId = accounts[0].Id, FirstName = 'Tess', LastName = 'Dachshund'));
insert contacts;
Test.stopTest();
}
}
The time savings for this type of trigger configuration can be huge and in situations where time is of the essence you may be well served by having something like this setup in your org.