1

I have apex code that dynamically creates SObject records based on configurations (metadata type records). The code needs to evaluate on-the-fly, if the Sobject field that should be "put" (sObjectRecord.put(fieldName, fieldValue) is from a read-only system field or a regular, writable field.

The code will run in system context, so this is not about permissions but about database enforced read-only fields.

Typical fields that should be recognized as read-only are:

  • CreatedDate, LastModifiedDate, etc
  • CreatedById, LastModifiedById, etc
  • All auto-number fields (custom and standard, such as Order.OrderNumber)
  • All formula fields
  • The standard id fields (Id)

My current code works like this:

public Boolean isWriteable() {

    // always return false for formula and autonumber fields
    if (fieldDescribe.isCalculated()) return false;
    if (fieldDescribe.isAutoNumber()) return false;

    // get all read-only system fields: they are not permissionable, accessible but not update/writable for current user
    if (!fieldDescribe.isPermissionable() && fieldDescribe.isAccessible() && !fieldDescribe.isCreateable() && !fieldDescribe.isUpdateable()) return false;

    // always return false for compound fields and other fields that are not intended to be written
    switch on fieldDescribe.getType() {
        when address { return false; }
        when base64 { return false; }
    }

    return true;

}

So far, the debug logs show me satisfying results. Anything I forgot? Please help me to improve the code.

1 Answer 1

2

I think you need to post this in the code review forum, instead.

Having said that, I think you're code looks good to establish if the field is writable, however when you're populating the field, you need to be aware of a lot of stuff. the DescribeFieldResult Class is helpful here:

  • Put your logic to populate the field in a try cactch block, because there are lots of gotchas.
  • If you're populating fields, make sure you're not overfilling the fields (i.e. if a text field can take 255 chars, and you fill it with 256 chars, or for number fields, you're checking that you're not exceeding the number of digits. You can use getDigits() / getPrecision()
  • if you're populating a picklist, make sure the value that you're populating it is allowed. You can use the getPicklistValues() and the isRestrictedPicklist() methods from the DescribeFieldResult Class
  • You also want to make sure that you're populating dependent picklists correctly. use isDependentPicklist()
4
  • Are you sure, that the put(fieldName, value) operation will already throw an execption? I think, most of validation will only be performed on Database calls (insert, update). Commented May 29, 2019 at 14:47
  • try this, and update the object and field name.... put(text_field__c, 'f'.repeat(Schema.SObjectType.YOUROBJECT.fields.text_field__c.getLength() + 1),); Commented May 29, 2019 at 15:07
  • Yes, I had validation rules in mind. They only fire on the actual database operation. Commented May 31, 2019 at 8:14
  • I also tried your code and it works without any exceptions. Commented May 31, 2019 at 9:16

You must log in to answer this question.

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