3

I understand this is a basic question. But how can I make sure that my code progresses further based on a Record Type of an object ? Is this approach okay?

1) Create an Util class with a static method which has a Describe call in it and returns Record Type Id by taking Record Type DeveloperName as input paramter

2) Store the Id of the Record Type in a custom label then compare it ?

3)

if(Util.getObjectRecordTypeId(Case.SObjectType, 'Trouble_Ticket') == Label.TroubleTicketTypeId)
    {
    // do something
    }

If anyone has a better approach then please share your idea.

1

I like your approach but instead of th ID I would save the developerName.

At runtime, you get the DevName of the record type by doing a call and then you compare it to the DevName you saved. That way, you don't need to worry about updating the ID when changing environments.

I have sample code that I can get if needed (it's Sat, so it's not handy... But retrievable if needed)

==Update==

Here is some sample code, you can adapt this many ways but I wanted to quickly stub it out for you.

The advantage of the first one is that you're not using SoQL (and limits). The disadvantage is that the name might change (it's unlikelier that you'll change the Dev Name)

=== USING RT Name ==

public class aClass() {
    private void compareRT(MyObject__c obj) {

      string rtId = RecordTypeCache.getRTId(Schema.MyObject__c.SObjectType, 'The_RT_Name'); //This is NAME, not Dev Name

      if (obj.RecordTypeID == rtId) {
        //Do Something
      }
    }
}

public class RecordTypeCache() { 

private static Map<String, Map<String,Schema.RecordTypeInfo>> rtsByObject = new Map<String, Map<String,Schema.RecordTypeInfo>>();

private string void getRTId(sObjectType object, string myRTName) {
   string objectName = object.getDescribe().getName(); 

  if (! rtsByObject.containsKey(objectName)) {
          rtsByObject.put(objectName, sObjectType.getDescribe().getRecordTypeInfosByName());

  }

  Map<String,Schema.RecordTypeInfo> recordTypeInfo = rtsByObject.get(objectName);

  if (! recordTypeInfo.containsKey(myRTName)) {
    //Throw an exception
  }

 return recordTypeInfo.get(myRTName).getRecordTypeId();;

}

}

=== USING the Developer Name ===

public class aClass() {
  private void compareRT(MyObject__c obj) {

  string rtId = RecordTypeCache.getRTId('MyObject__c', 'The_RT_Name'); //This is DEV NAME, not Name

  if (obj.RecordTypeID == rtId) {
    //Do Something
  }
}

}

public class RecordTypeCache() { 

private static Map<String, Map<String, RecordType>> rtInfo = new Map<String, Map<String, RecordType>>(); 

private string void getRTId(string sObjectName, string myRTName) {

   if (! rtInfo.containsKey(sObjectName) {
     RecordType allRt = [SELECT Id, DeveloperName
                      FROM RecordType 
                      WHERE SObjectType= :sObjectName];

    Map<String, RecordType> rtObject = new Map<String, RecordType>();

    for (RecordType rt : allRT) {
      rtObject.put(rt.DeveloperName, rt);
    }

    rtObject.put(sObjectName, rtObject);
  }

  Map<String, RecordType> rtObject = rtInfo.get(sObjectName);

  if (! rtObject.containsKey(myRTName)) {
    //Throw an exception
  }

  return rtObject.get(myRTName).id;


   }
}
6
  • 1
    Sample code ready for you! – Sebastian Kessel Dec 5 '15 at 16:44
  • ==Using RT Name== object. getName() is not correct signature it seems i.e. [Schema.SObjectType].getName() is not a method – Jarvis Dec 6 '15 at 4:28
  • Oops. Add "getDescribe()" before getName(). I'll update the code tomorrow – Sebastian Kessel Dec 6 '15 at 6:48
  • 1
    @Bennie you're right I'm sorry. This is what happens when I type too fast. It would be "object.getDescribe().getName()" Instead. My apologies, I think this will fix it once and for all. Obviously, the same applies to the "getName()" you'll see immediately after. – Sebastian Kessel Dec 6 '15 at 7:40
  • 1
    @Bennie, I just corrected the sample (and going to sleep). I'll check for any more comments tomorrow morning – Sebastian Kessel Dec 6 '15 at 8:17
1

Yes by using describe call, getting recordTypeId then compare recordType its ok.

I like the approach to recordType based on sobjectType and developer. And use id for compare.

RecordType rt = [SELECT Id FROM RecordType 
                        WHERE SObjectType='OBJECT_NAME_HERE' 
                        AND Name='RECORDTYPE_NAME_HERE' LIMIT 1];

Or utility class

public class ObjectUtil 
{
    public static String getObjectRecordTypeId(SObjectType sObjectType, String recordTypeName)
    {
        //Generate a map of tokens for all the Record Types for the desired object
        Map recordTypeInfo = sObjectType.getDescribe().getRecordTypeInfosByName();

        if(!recordTypeInfo.containsKey(recordTypeName))
            throw new RecordTypeException('Record type "'+ recordTypeName +'" does not exist.');

        //Retrieve the record type id by name
        return recordTypeInfo.get(recordTypeName).getRecordTypeId();
    }

    public class RecordTypeException extends Exception{}
}

String recordTypeId = ObjectUtil.getObjectRecordTypeId(Lead.SObjectType, 'RECORDTYPE_NAME');

Its depend on you which approach you want to use.

I prefer personally

use describe call once store the all values in some variable and use again & again.

So this way you don't have use describe call again & again. and execution process will be sort.

4
  • I didn't get the part where you said "use describe call once store the all values in some variable and use again & again." Please elaborate – Jarvis Dec 5 '15 at 16:56
  • 2
    Bennie, The pattern @Ratan is talking about involves "saving" the information into a static variable so you don't have to continue making describe (or SoQL) calls to retrieve them. This is especially nice if you have several objects. I just updated my answer above to reflect this. Though I just updated the first example, you can easily adapt it to the second one. – Sebastian Kessel Dec 5 '15 at 17:24
  • 1
    I had time... so I adapted the 2nd example too. :) – Sebastian Kessel Dec 5 '15 at 17:33
  • @Bennie yes for example you can store recordid and there developer store into a map. You can use this map as many time you want – Ratan Paul Dec 5 '15 at 18:12
1

Using the pattern below, your item 3 becomes

Case c = ...;
if (CaseRecordType.instance(c.RecordTypeId) == CaseRecordType.TICKET) {
    ....
}

Using this "typesafe enum pattern" your code can be a bit more self documenting and less prone to mixing up method parameters.

The class would look like this:

public class CaseRecordType {

    private static final Map<String, RecordTypeInfo> INFOS =
            SObjectType.Case.getRecordTypeInfosByName();
    private static final Map<Id, CaseRecordType> TYPES =
            new Map<Id, CaseRecordType>();

    // Use these in the code
    public static final CaseRecordType TICKET = new CaseRecordType('Trouble Ticket');
    public static final CaseRecordType OTHER1 = new CaseRecordType('Other 1');
    public static final CaseRecordType OTHER2 = new CaseRecordType('Other 2');
    ...

    // Use this to get the type object given an ID from an SObject
    public static CaseRecordType instance(Id rtId) {
        return TYPES.get(rtId);
    }

    // Use this if you want to loop over all the values defined here
    public static CaseRecordType[] values() {
        return TYPES.values();
    }

    // Reference these fields as needed in code
    public String name {get; private set;}
    public Id recordTypeId {get; private set;}

    // Only allow values to be created in this class
    private CaseRecordType(String name) {
        this.name = name;
        this.recordTypeId = INFOS.get(name).getRecordTypeId();
        TYPES.put(recordTypeId, this);
    }
}

and methods in your code would have this signature:

    Case c = ...;
    CaseRecordType ct = CaseRecordType.instance(c.RecordTypeId);
    doSomething(ct);

private method doSomething(CaseRecordType ct) {
    ...
}

instead of the less clear:

private method doSomething(Id caseRecordTypeId) {
    ...
}

or:

private method doSomething(String caseRecordTypeDeveloperName) {
    ...
}

Other data and other methods can be added to the CaseRecordType encapsulating the differences for the various types in one place.

See Favour the Typesafe Enum pattern in Apex for a bit more information on the pattern.

2
  • I agree Keith, the question of my title is misleading. Still your post answers my question – Jarvis Dec 5 '15 at 17:14
  • 1
    @Bennie Just edited the answer to try to better match your question. – Keith C Dec 5 '15 at 17:16

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.