3

I would like to manage the validation of my record's RecordTypeIds, against the valid Ids which are listed in a Custom Setting, in a Class.

Based on the answer to this question How to get values from class to trigger, it looked like I'd have to use up an SQOL query to access the list of valid RecordTypeIds from the Class.

But I've noticed that if I create an object with the Class in my Trigger

WE_RecordTypeChecker rtc = new WE_RecordTypeChecker();

Then using the dot notation, rtc.validRecordTypeIds; I seem to have access to the Class static variable. This example causes an error

Class static variable cannot be accessed via object instance

but I'm hoping that by changing the list's signature, that can be fixed.

Is there any way that I can retrieve the list without using up an SOQL query? Even if it means calling the Class's method from another Class..

If I can retrieve the list, then I'll use the valid Ids as an input for my next Class and check that the RecordTypeIds, of the records in the Class, are contained in the list of valid Ids.

If not then I can just retrieve the valid Ids in my Trigger but since I'm using the One Trigger Per Object design pattern, I'd like to keep the trigger as simple as possible.

Class

public class WE_RecordTypeChecker {

    //Variables
    public static List<WEID__c> weids = WEID__c.getall().values();
    public static Set<Id> validRecordTypeIds;

    //Constructor
    public static void validate(SObject[] oldSobs, SObject[] newSobs) {
        if (oldSobs != null) validate(oldSobs);
        if (newSobs != null) validate(newSobs);
    }

    //Method: retrieve RecordTypeIds from Custom Setting
    private static void validate(SObject[] sobs) {

        //check object type & retrieve valid Ids from Custom Setting
        SObjectType t = sobs[0].getSObjectType();
        if (t == Opportunity.SObjectType) {
            for(WEID__c weid : weids) {
                try {
                    validRecordTypeIds.add(weid.WEOppId__c);
                } catch (System.StringException e) {
                    System.debug(System.LoggingLevel.ERROR,'Invalid Record Type Id ' + weid.WEOppId__c);
                }
            }
        } else if (t == MPM4_BASE__Milestone1_Project__c.SObjectType) {
            for(WEID__c weid : weids) {
                try {
                    validRecordTypeIds.add(weid.WEProjectId__c);
                } catch (System.StringException e) {
                    System.debug(System.LoggingLevel.ERROR,Invalid Record Type Id ' + weid.WEProjectId__c);
                }
            }
        }
    }
}

Class Trigger

RecordTypes.validate(Trigger.old, Trigger.new);
2
  • Do you not just need to use WE_RecordTypeChecker.validRecordTypeIds and not use an instance variable? Jul 12 '15 at 10:30
  • @RichardDurrant thanks for the suggestion, do you mean I should use that in my trigger or?
    – Alex S
    Jul 12 '15 at 10:44
3

Not entirely sure what your aim is with this code. If it is to check if the record type is present in the custom setting then this would do that:

public class WE_RecordTypeChecker {

    // Make referencable from another class
    public static Set<Id> validIds = new Set<Id>();
    static {
        for (WEID__c weid : WEID__c.getall().values()) {
            validIds.add(weid.WEOppId__c);
            validIds.add(weid.WEProjectId__c);
        }
    }

    public static void validate(SObject[] oldSobs, SObject[] newSobs) {
        if (oldSobs != null) validate(oldSobs);
        if (newSobs != null) validate(newSobs);
    }

    private static void validate(SObject[] sobs) {
        for (SObject sob : sobs) {
            Id id = sob.get('RecordTypeId');
            if (!validIds.contains(id)) {
                sob.addError('Invalid record type');
            }
        }
    }
}

This works because the record type IDs are unique and so don't need qualifying by the SObjectType.

In logic like this, you do not need multiple instances of the data that you would get by creating a new object. The list custom setting data is fixed, so only needs converting once into the usable form of the set of ID values.

You can reference the ID values from another class like this:

Set<Id> ids = WE_RecordTypeChecker.validIds;

though it might be better to add additional methods to this class than to just share the data.

3
  • Thanks Keith you're right about not needing to qualify the SObject Type. The problem that I'm trying to solve is accessing the list of valid RecordTypeIds from another method, either by retrieving it in my Trigger and using it as an input for my next Class or calling the method from the next Class.
    – Alex S
    Jul 12 '15 at 11:14
  • I'll use the same check in every Class that I create so I'm looking for a way to avoid replicating it each time - because of character limits, maintenance etc.
    – Alex S
    Jul 12 '15 at 11:20
  • @AlexS I've edited the answer a bit to address that.
    – Keith C
    Jul 12 '15 at 11:26
1

This can help you, a simple helper class that gives you the recordtype id

public class RecordTypeHelper {
public static ID GetRecordTypeIdByName(string sobjectname, string recordtypename){
    ID result = null;
    list<Schema.DescribeSObjectResult> doResults = 
        Schema.describeSObjects(new List<String>{sobjectname});

    for(Schema.DescribeSObjectResult d : doResults){
       map<string,Schema.RecordTypeInfo> rtypes = d.getRecordTypeInfosByName();
        if (rtypes.containsKey(recordtypename)){
            result = rtypes.get(recordtypename).getRecordTypeId();
        }
    }
    return result;
}

}

1
  • 1
    Thanks Danny, I'm actually thinking about switching to using the RecordTypeName to validate my records soon (with the record's name in a formula field) so I may use a version of your code then.
    – Alex S
    Jul 12 '15 at 18:20

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.