Skip to content

AfterUndelete.Writer

Creates, updates or deletes other records, or publishes platform events, when records are restored. Register the changes on the unit of work; they commit with the restore.

Interface

apex
public class AfterUndelete {
    public interface Writer extends Handler {
        Boolean writeOnAfterUndeleteWhen(TriggerHandler.UndeleteRecord record);
        void writeOnAfterUndelete(TriggerHandler.UndeleteRecord record, TriggerHandler.UnitOfWork unitOfWork);
    }
}
  • writeOnAfterUndeleteWhen(record): called once per record in the chunk. Return true to write for the record.
  • writeOnAfterUndelete(record, unitOfWork): called right after its predicate returns true, with this Writer’s unit of work.

Example

apex
public with sharing class ContactWriter implements AfterUndelete.Writer {
    public Boolean writeOnAfterUndeleteWhen(TriggerHandler.UndeleteRecord record) {
        return record.isNotNull(Contact.AccountId);
    }

    public void writeOnAfterUndelete(TriggerHandler.UndeleteRecord record, TriggerHandler.UnitOfWork unitOfWork) {
        unitOfWork.toInsert(new Task(WhatId = ((Contact) record.getNewSObject()).AccountId, Subject = 'Review contact'));
    }
}
apex
public with sharing class AccountRestoreGuardWriter implements AfterUndelete.Writer {
    public Boolean writeOnAfterUndeleteWhen(TriggerHandler.UndeleteRecord record) {
        return !FeatureManagement.checkPermission('Restore_Accounts');
    }

    public void writeOnAfterUndelete(TriggerHandler.UndeleteRecord record, TriggerHandler.UnitOfWork unitOfWork) {
        record.getNewSObject().addError('You are not allowed to restore accounts.');
    }
}

Good to Know

  • Register, don't run DML. The library commits what you register on unitOfWork after the last handler. Direct DML is not blocked here, but it runs at once, outside the unit of work.
  • A self-update is a second save. unitOfWork.toUpdate(new Account(Id = record.getId(), …)) fires BeforeUpdate and AfterUpdate for the restored record.
  • A self-delete fails. A toDelete of a record being restored throws a DmlException with SELF_REFERENCE_FROM_TRIGGER. Block the restore with addError instead.
  • Block a restore with addError. There is no Validator here. Call record.getNewSObject().addError(…), as in the second tab, and list this Writer first. The record stays in the Recycle Bin.
  • Writer wins. A class that also implements AfterUndelete.Dispatcher runs only as a Writer.

Test

apex
@IsTest
static void writeOnAfterUndeleteRejectsRestore() {
    // Setup
    Account restoredAccount = new Account(Name = 'Acme');

    // Test
    new AccountRestoreGuardWriter().writeOnAfterUndelete(new TriggerHandler.TriggerRecord(restoredAccount, null), null);

    // Verify
    Assert.areEqual('You are not allowed to restore accounts.', restoredAccount.getErrors()[0].getMessage(), 'The restore should be rejected.');
}