Polymorphic Id field is a lookup field which can reference several different type of SObjects, such as the Whoid and Whatid field on the Event object. As of now, the Polymorphic Id field is only available in standard fields. Please vote for the idea Custom Polymorphic Id field (WhoId/WhatId) if you think that it’s an important feature for you.
This article will discuss how to implement the polymorphic behavior for your custom fields. Let’s assume you have the following business requests:
- Three custom media objects need to be created, Image__c, Audio__c and Video__c.
- A lookup field (Account__c) to Account on each media object needs to be created.
- A media request object (MediaRequest__c) needs to be created to represent to request to media object.
- A lookup field (Media__c) on MediaRequest__c object needs to be created. The target the lookup field can be either Image__c, Audio__c or Video__c object.
- ONE related list for all associated related media objects needs to be created on Account object.
#4 and #5 are typical polymorphic behavior requests.
The application will typically be modeled as the diagram shown above. There is no polymorphic behavior support and requests #4 and #5 are not fulfilled.
In order to support the polymorphic behavior, we need to be creative with the data model. Let us check the diagram below.
The major difference from the previous data model is that a Media__c parent (Master-Detail) object is introduced and acts as a bridge for the child media objects to others (Account and Media_Request__c). The idea is to use Media__c as a proxy. It hides the difference for its child objects and routes all the requests to its child objects.
Here are the highlights of the new data model.
- Media__c object is created as the parent (Master-Detail) to Image__c, Audio__c and Video__c objects.
- Media_Type__c is a Picklist field on Media__c object which has three values: Image, Audio and Video.
- Child_Id__c is a TEXT(18) field on Media__c object which is used to store the ID value of the associated child media object. Checking “Unique” checkbox to help to enforce the 1:1 relationship from Media__c to its child objects.
- Account__c is a Lookup field to Account on Media__c object which is used to eliminate the individual Lookup field on each Image__c, Audio__c and Video__c objects. The benefit is that only one related list is needed on Account page layout instead of three which fulfill the business request #5.
- ONLY one Media__c Lookup field is created on MediaRequest__c instead of three which fulfill the business request #4.
Here are the reasons why we use “Master-Detail” instead of Lookup to model the relationship from Media__c to its child objects.
- The same security access is enforced for both Media__c and its child objects. This is important when you need control the sharing for the media objects.
- The child object will be deleted automatically when parent Media__c object is deleted.
We are done with the declarative development tasks. We now need to dive into the code to play some tricks to fully implement polymorphic behavior requests.
Enforce 1:1 relationships between Media__c and its child object
Similar to the Account and Contact objects in PersonAccount, Media__c and its child object should exist always in-pair. As mentioned before, the Child_Id__c field on Media__c is used to store the Id of the child object. We use trigger to populate the field to establish the 1:1 relationship. The trigger is created on the child objects and populates the Id value to its parent Media__c object.
Code snippet for Audio__c trigger.
Since Image__c and Vidoe__c have the same logic, we create the MediaTriggerHandler class to wrap up the logic. You can check the zipped source code at the bottom of this blog.
Redirect Edit/View requests from Media__c to its correspondent child object
Since Media__c is the proxy object, we need to redirect the requests for Media__c object to its child objects. The Edit/View requests can be done with a dispatcher Visualforce page. The dispatcher Visualforce page is used to override the default Edit and View actions of Media__c object.
See the code snippet the dispatcher page. The dispatchView() and dispatchEdit() methods will be invoked as the page action which routes the request to its child object.
Overide New button requests for Media__c
New request is different from View and Edit requests. We cannot redirect the New request because the the child object is not created yet. We need to create Media__c and its child object in-pair according to the media type selected. We still use Visualforce page (MediaNew) to implement it. The MediaNew Visualforce page is used to override the New action of the Media__c object.
Three different Visualforce components are created for each type of media object. Different page logic can be isolated and encapsulated into different Visualforce component.
In MediaNew Visualforce page, we use <apex:actionFunction/> to control which of the Visualforce component is rendered according to the media type selected.
See the finalized MediaNew Visualforce page. Different Visualforce component is displayed for different Media type selected.
Now we have done the coding for the polymorphic requests. Let us check how it works.
For the #4 request, only one Lookup field is created and different type of media objects can be selected for the Media Lookup field.
For the #5 request, the related list on Account page layout contains mixed type of media objects. The link on the related list will bring you directly to the Edit or View page of the child media object.
You can download the sample project source files from GitHub.