5

What's the best way to get the Id of the custom setting referenced in MyCustomSetting__c.getInstance() for a hierarchical custom setting?

I'm trying to update your current instance of a custom setting via apex, but can't seem to get the Id (therefore no update possible) from .getInstance().Id. What am I missing?

11

A few things to take into consideration:

  1. Are you accessing from a test method - If so you must insert a custom setting first
  2. Is there a record for the Specified "Instance" for the current context user?

If no custom setting for the current user is defined then it returns a new custom setting and the ID will be blank. Otherwise the getInstance() should return the ID:

CustomSettingExample__c cs = CustomSettingExample__c.getInstance();

//cd.id - should NOT be null if a custom setting exists for the current context user.

See Custom Settings Methods:

If no custom setting data is defined for the user, this method returns a new custom setting object. The new custom setting object contains an ID set to null and merged fields from higher in the hierarchy. You can add this new custom setting record for the user by using insert or upsert. If no custom setting data is defined in the hierarchy, the returned custom setting has empty fields, except for the SetupOwnerId field which contains the user ID.

If you need more detailed answer then you may be better served by posting your code so we can tell if it is a problem with your code or not.

  • That's what was missing. I had a profile setting configured, but not a user setting. – Nathan Williams Jul 9 '15 at 3:35
  • @NathanWilliams Note that if you use CustomSettingExample__c.getOrgDefaults() you will get an ID that you can use to update that custom setting later. – Willem Mulder Jul 7 '17 at 15:03
1

I ended up solving my use case.

I am building out @testSetup functionality in my org to reduce test runtimes (since I batch all test classes to run daily), and utilize a UtilTest class to house my test data creation methods as well as some stock variables (a generic Account acc that can be used anywhere easily without having to recreate over and over again). However, @testSetup appears to not maintain it's instantiation when transitioning from @testSetup to @isTest.

@isTest
public with sharing class UtilTest {

    public static Account buildAccount() {
        return new Account(
            Name = 'Test Account',
            RecordTypeId = System.Label.RecordTypeIdAccountStandard
        );
    }

    public static Account acc {
        get {
            if (acc == null) {
                if (UtilCustomSettings.TestSettings.Account__c == null) {
                    acc = buildAccount();
                    insert acc;
                    UtilCustomSettings.updateTestSettings('Account__c', acc.Id);
                } else {
                    acc = new Account(Id = UtilCustomSettings.TestSettings.Account__c);
                }
            }
            return acc;
        }
    }

}

I reference UtilCustomSettings.TestSettings everywhere in my org when I need to access TestSettings__c. When I need to update the running user's most applicable instance, I call UtilCustomSettings.updateTestSettings() which references setTestSettingsId() to traverse up the chain (check for me first, then my profile, then my org) to grab that Id and use it for any further updates moving forward.

An example is when I instantiate the UtilTest.acc variable somewhere in my @testSetup class, I then store the Id that's created in your most applicable custom setting level (along with all other created variables, like a Contact con and a Lead l), which are then recalled from the custom setting in the @isTest methods later instead of recreating the variables from scratch (since they are wiped clean between @isTest methods). This avoids noisy DML operations as much as humanly possible!

public with sharing class UtilCustomSettings {

    public static TestSettings__c TestSettings {
        get {
            if (TestSettings == null) {
                if (Test.isRunningTest() && TestSettings__c.getInstance().Name == null)
                    UtilTest.buildTestSettings();
                TestSettings = TestSettings__c.getInstance();
            }
            return TestSettings;
        }
        set;
    }

    public static Map<Id, Id> TestSettingsIds {
        get{
            if (TestSettingsIds == null) {
                TestSettingsIds = new Map<Id, Id>();
                for (TestSettings__c setting : [SELECT Id, SetupOwnerId FROM TestSettings__c]) {
                    TestSettingsIds.put(setting.SetupOwnerId, setting.Id);
                }
            }
            return TestSettingsIds;
        }
        set;
    }

    public static void setTestSettingsId() {
        if (TestSettings.Id == null) {
            TestSettings.Id = TestSettingsIds.get(TestSettingsIds.containsKey(UserInfo.getUserId()) ? UserInfo.getUserId() : (TestSettingsIds.containsKey(UserInfo.getProfileId()) ? UserInfo.getProfileId() : UserInfo.getOrganizationId()));
        }
    }

    public static void updateTestSettings(String field, Object value) {
        setTestSettingsId();
        TestSettings__c setting = new TestSettings__c(Id = TestSettings.Id);
        setting.put(field, value);
        update setting;
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.