3

In an effort to write reusable code, I am trying to move my field-level security check code into a common class/methods.

Because the Schema.SObjectType is dynamic, I am looking for a way to pass that type (e.g. Account, Contact, Custom__c, etc...) to a method like so:

private void CheckReadPermissions(Schema.SObjectType sObjectType, String[] fields) {
    Map<String, Schema.SObjectField> fieldMap = sObjectType.fields.getMap();
    ....
}

I want to do some something like this:

// check permissions
CheckReadPermissions(Schema.SObjectType.Contact, new String[] { 'Id', 'Name' });

This fails to compile, complaining that the variable does not exist:

message: 'Variable does not exist: fields'

Does anyone know how to accomplish what I'm trying to do here (pass in a type as an article, assuming that's what it is)?

3 Answers 3

5

The SObjectType.<ObjectName> syntax actually refers to a DescribeSObjectResult. So you'd have to either pass in a DescribeSObjectResult, or call the getDescribe method yourself:

Map<String, Schema.SObjectField> fieldMap = sObjectType.getDescribe().fields.getMap();

Or...

void CheckReadPermissions(DescribeSObjectResult sObjectType, String[] fields) {

Which you would call as:

CheckReadpermissions(SObjectType.Account, new String[] { 'Id','Name' });

Execute Anonymous Example

void CheckReadPermissions(DescribeSObjectResult describeResult, String[] fields) {
    Map<String, SobjectField> fieldMap = describeResult.fields.getMap();
    for(String field: fields) {
        System.debug(fieldMap.get(field).getDescribe().isAccessible());
    }
}
CheckReadpermissions(SObjectType.Account, new String[] { 'Id','Name' });
5
  • Thanks for the answer. Unfortunately, SObject.Account does not compile. Mar 8, 2018 at 19:41
  • @SwisherSweet Oops, yeah, that was a typo. Should have been SObjectType.Account
    – sfdcfox
    Mar 8, 2018 at 19:43
  • @SwisherSweet Also added an exec anon example you can try out.
    – sfdcfox
    Mar 8, 2018 at 19:45
  • 1
    Thanks sfdcfox. That did the trick. Not sure why this threw me so much. I guess I couldn't connect SObjectType.Account is a type of DescribeSObjectResult from what I read in the docs (and still can't based on docs). Magic variables. Mar 8, 2018 at 19:50
  • @SwisherSweet It is indeed a magic variable. No more need to call SObjectType.getDescribe.
    – sfdcfox
    Mar 8, 2018 at 20:07
3

It seems that SObjectType and DescribeSObjectResult are confused here.

If you call your code as following:

Map<String, Schema.SObjectField> fieldMap = sObjectType.getDescribe().fields.getMap();

it will work as expected.

Basically, class SObjectType has method getDescribe which will return you instance of DescribeSObjectResult that has field and other properties.

Documentation is here

1
  • Thanks for your answer. Based on your answer, I wasn't sure where to make my changes, so I tried many things, but none worked. Would you mind updating your answer to provide a complete example of method signature and how it should be called? Mar 8, 2018 at 19:43
0

If your function can accept an array of SObjectField then you don't need to pass in the SObjectType:

@isTest
private without sharing class MyTestClass1 {
    @isTest
    private static void myTest() {
        CheckReadPermissions(new SObjectField[] { Contact.Fields.Id, Contact.Fields.Name });
    }
    
    private static boolean CheckReadPermissions(SObjectField[] fields) {           
        for (SObjectField field : fields) {
            if (field.getDescribe().isAccessible() == false) {
                return false;
            }
        }
        return true;
    }
}

If you want to maintain the ability to pass in an array of strings, you could do:

@isTest
private without sharing class MyTestClass2 {
    @isTest
    private static void myTest() {
        CheckReadPermissions(Contact.SObjectType, new String[] { 'Id', 'Name' });
    }
    
    private static boolean CheckReadPermissions(SObjectType objType, String[] fields) {
        Map<String, SObjectField> fieldMap = objType.getDescribe().fields.getMap();
        
        for (String field : fields) {
            if (fieldMap.get(field).getDescribe().isAccessible() == false) {
                return false;
            }
        }
        return true;
    }
}

You could use the original syntax of "SObjectType.Contact" instead of "Contact.SObjectType", but I think this is harder to read:

@isTest
private without sharing class MyTestClass3 {
    @isTest
    private static void myTest() {
        CheckReadPermissions(SObjectType.Contact, new String[] { 'Id', 'Name' });
    }
    
    private static boolean CheckReadPermissions(DescribeSObjectResult objResult, String[] fields) {
        Map<String, SObjectField> fieldMap = objResult.fields.getMap();
        for (String field : fields) {
            if (fieldMap.get(field).getDescribe().isAccessible() == false) {
                return false;
            }
        }
        return true;
    }
}

I realize the question is several years old, but adding the answer here for future googlers. I found this page via the search: "pass sobject type as parameter apex"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .