Логика в Trigger с помощью Switch

Думаю, что вы уже знакомы с такой конструкцией как switch . Она примется во многих языках программирования. С недавних пор язык Apex перестал быть исключением и тоже обзавёлся таким дополнением.

Не будем останавливаться на принципах и синтаксисе работы Switch. Перейдём у сути.

Взаимодействие Switch и Trigger

До того как начнём, стоит обратить внимание на новую переменную из контекста триггера.
Довольно долго в Trigger классе было 7 булевых переменных для определения контекста вашего триггера (before/after and insert/update/delete/undelete). Но для передачи этой информации о состоянии триггера придётся передавать каждое состояние отдельно, или же создавать собственную структуру. Более лёгкий путь немного ниже. :arrow_down:

Trigger.operationType

Итак, теперь у нас есть просто способ для определения состояния триггера. Все 7 переменных были завёрнуты в переменную enum типа названую Trigger.operationType .

  • BEFORE_INSERT
  • AFTER_INSERT
  • BEFORE_UPDATE
  • AFTER_UPDATE
  • BEFORE_DELETE
  • AFTER_DELETE
  • AFTER_UNDELETE

Если объединить эту переменную и Apex switch, то код нашего триггера станет куда лучше.

Switch и Enum в триггере

Предположим, существует триггер и мы следуем лучшей практике: один триггер для одного типа объекта. Нам необходимо имплементировать следующий функционал в нём:

  • Создать related записи в after insert и after update контексте
  • В before insert задать некоторые значения
  • В некоторых случаях предотвратить удаление данных в before delete
trigger AccountTrigger on Account (before insert, after insert, before update, after update, before delete, after delete, after undelete) {
    if (Trigger.isAfter) {
        if (Trigger.isInsert || Trigger.isUpdate) {
            //create related records
        } else if (Trigger.isDelete){
            //prevent deletion of sensitive data
        }
    } else {
        if (Trigger.isInsert) {
            //set value on record create
        }   
    }
}

Эта логика будет работать нормально, но в будущем будет сложно понять с первого взгляда, что за чем происходит.

Теперь давайте попробуем приметь наш новый метод. Последуем старой практике и передадим переменную в статический метод класса хендлера.

trigger AccountTrigger on Account (before insert, after insert, before update, after update, before delete, after delete, after undelete) {
    AccountTriggerHandler.handleTrigger(Trigger.new, Trigger.old, Trigger.operationType);
}

В этом небольшом примере мы вызываем метод handleTrigger и передаем ему переменную Trigger.operationType . Далее хендлер сможет узнать всё о состоянии триггера. Давайте посмотрим детальнее, что происходит внутри хендлера:

public with sharing class AccountTriggerHandler { 

    public static void handleTrigger(List<Account> newRecords, List<Account> oldRecords, System.TriggerOperation triggerEvent ) {
    
        switch on triggerEvent {
        
            when AFTER_INSERT, AFTER_UPDATE {
                //create related records
            }
            when BEFORE_INSERT {
                //set value on record create
            }
            when AFTER_DELETE {
                //prevent deletion of sensitive data
            }
            when else {
                //do nothing for AFTER_UNDELETE, BEFORE_DELETE, or BEFORE_UPDATE
            }
        }
    }
}

Так понятнее, верно ?

3 Likes

Було б цікаво ще розглянути Marge

1 Like

Обов’язково напишу про це також :slight_smile: