Search code examples
triggerssalesforceapex

Apex trigger firing on dynamically referenced fields from Custom Metadata


I am running into a skill wall when attempting this current problem. I have a custom object (Acq__c) that has a series of lookup fields on it to User. When these fields are updated, specific related child objects are updated to reflect the new User associated. This initial part is fine. However, there is a need to be able to expand the fields this functionality works on. So if a new LookUp field is built - it can easily be granted this same functionality. I was hoping to do this by using Custom Metadata Types. In this case, the trigger controlling the update functionality would query the Custom Metadata Type records, find all the fields on the Acq__c object that should have this update functionality, test to see if they have been updated in the DML statement, and then fire appropriately based on which ones have been updated. This would allow for any user creating new lookups in the future, to add them to the Acq__c object, and then update the Metadata to expand the trigger to the new field.

The straight forward portion of the trigger, updating, etc - I don't have any issues with. Once I query the Custom metadata and have a list of records that each contain an API for a field on the Acq__c object - I'm unsure how to use this record list to see what fields have been updated, and then accordingly would need to fire the child object update.

I hope all that makes sense - any help would be super appreciated.

N


Solution

  • Custom metadata might be overkill for it, have a look into fieldsets? They're bit of a relic now (they were super useful in Visualforce pages, not so much in LWC) but still - they'd sit "closer" to the object being changed, more likely admin won't forget to change them.

    Once you have your list (or set) of field API names you can loop over your trigger.new. Something like that

    Set<String> watchedFields = new Set<String>();
    for(Schema.FieldSetMember fsm : sObjectType.Acq__c.FieldSets.MyFieldsetNameHere.getFields()){
        watchedFields.add(fsm.getFieldPath());
    }
    System.debug(watchedFields);
    Map<Id, Acq__c> recordsWithKeyFieldsChanged = new Map<Id, Acq__c>();
    
    for(Acq__c acq : trigger.new){
        Acq__c old = trigger.oldMap.get(acq.Id);
        for(String field : watchedFields){
            if(acq.get(field) != old.get(field)){
                recordsWithKeyFieldsChanged.add(acq);
                break;
            }
        }
    }
    System.debug(recordsWithKeyFieldsChanged);
    if(!recordsWithKeyFieldsChanged.isEmpty()){
        doSomething(recordsWithKeyFieldsChanged);
    }
    

    It's loop in a loop so not great but would be tricky to do it without crafting a huge hardcoded if statement. And worst case it'll work what, 200 records multiplied by how many fields? ~10? The limit is 40 "Custom Relationship Fields" so not the end of the world.