Apex and Object References

I learned something today that I’m not sure how I made it this far without knowing. It was confusing the heck out of me, so I thought I’d share. When you assign one object to another through the use of the “=” operator, it doesn’t actually make a copy of the object. Instead, it makes a reference to the object. What does this mean? Let me try to explain with some code:

Account a = new Account(Name = 'Test');
Account b = a; //here we set a reference to a
b.Name = 'Changed'; //changing b also changes a
System.assertEquals('Changed', a.Name);

If you want to make a copy of the object, then you need to use the clone method to make a copy of the object:

Account a = new Account(Name = 'Test');
Account b = a.clone();
b.Name = 'Changed';
System.assertEquals('Test', a.Name);

Deleting Salesforce Contacts You Don’t Own (Part 2)

Back in October, I posted a way to allow users to delete contacts that they don’t own. The biggest problem I had with the method was that there was no way to test if the user requesting the delete should really be able to delete it (I wanted to say if the user had at lease edit permissions, then she could delete it). With the Spring release of Salesforce, there was a new object quietly exposed to Apex that makes this so easy. That object is the UserRecordAccess object. You can now query this object with SOQL to find out a user’s access to a specific record.

Let’s take a look. In its simplest form, you can query to see what the maximum access a user has to a particular object:

SELECT RecordId, MaxAccessLevel FROM UserRecordAccess WHERE UserId = [single ID] AND RecordId = [single ID]

Very elegant, right? Before we had access to this object, we’d have to do some major hackery by wrapping some dml in a try…catch statement to see what was possible.

So, how does this help us? We can now check to see if the record Id passed to the class can be edited by the user and if so, delete it because the class uses the without sharing keyword, so it ignores these permissions. The new and improved code!

global without sharing class ContactUtil {
  webService static String deleteContact(Id id) {
    Contact c = new Contact(id = id);
    try {
      UserRecordAccess ura = [select RecordId, HasEditAccess from UserRecordAccess where UserId = :UserInfo.getUserId() and RecordId = :id];
      if (ura.HasEditAccess)
        delete c;
      else
        throw new deleteException('Error deleting');
      return '';
    } catch (Exception e) {
      return e.getMessage();
    }
  }
}

Everything from the original post works exactly the same. As a bonus, here’s a link to an unmanaged package with the code (with test class!) and button: https://login.salesforce.com/packaging/installPackage.apexp?p0=04tU0000000URcs.