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.

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()
  • 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). – J. Lietzau May 29 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),); – PartOfTheOhana May 29 at 15:07
  • Yes, I had validation rules in mind. They only fire on the actual database operation. – J. Lietzau May 31 at 8:14
  • I also tried your code and it works without any exceptions. – J. Lietzau May 31 at 9: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.