Combining similar code with different objects
I have 4 very similar code blocks in a trigger that deal with synchronizing record type changes from Opportunity to its children. The only difference between them is that they do work on different custom objects. Since the actual work they do is identical, it seems like I should be able to combine them using a generic object type but I'm a little fuzzy on how to do it (assuming I even should).
(Note: I'm interested in general best practice here, not how to refactor specific code. Links are acceptable!)
My repetitive code looks something like this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete, after delete) {
if (Trigger.isAfter && Trigger.isUpdate) {
// Get record type map
List<String, Id> rtMap = OpportunityHelper.getRecordTypeMap();
// Update lists
List<Custom_Object1__c> obj1Updates = new List<Custom_Object1__c>();
List<Custom_Object2__c> obj2Updates = new List<Custom_Object1__c>();
// Get object 1 records
List<Custom_Object1__c> obj1List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object1__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Get object 2 records
List<Custom_Object2__c> obj2List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object2__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Map to opportunities
Map<Id, List<Custom_Object1__c>> oppId2Obj1Map = OpportunityHelper.mapify(obj1List);
Map<Id, List<Custom_Object2__c>> oppId2Obj2Map = OpportunityHelper.mapify(obj2List);
for (Opportunity o : Trigger.new) {
// Get record type of opportunity
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
// Get opportunity children
List<Custom_Object1__c> obj1List = oppId2Obj1Map.get(o.Id);
List<Custom_Object2__c> obj2List = oppId2Obj2Map.get(o.Id);
// Sync up obj1 record types
for (Custom_Object1__c obj1 : obj1List) {
// Get record type names of child
String rtObj1 = OpportunityHelper.getRecordTypeName(obj1.RecordTypeId);
// If record types don't match, change the record type of obj1
if (rtOpportunity <> rtObj1) {
obj1.RecordTypeId = rtMap.get(rtOpportunity);
obj1Updates.add(obj1);
}
}
// Sync up obj2 record types
for (Custom_Object2__c obj2 : obj2List) {
// Get record type names of child
String rtObj2 = OpportunityHelper.getRecordTypeName(obj2.RecordTypeId);
// If record types don't match, change the record type of obj2
if (rtOpportunity <> rtObj2) {
obj2.RecordTypeId = rtMap.get(rtOpportunity);
obj2Updates.add(obj2);
}
}
}
// Process record type changes
if (obj1Updates.size() > 0) update obj1Updates;
if (obj2Updates.size() > 0) update obj2Updates;
}
}
So...is there some way I can use a generic object type to minimize my repetitive code here? Maybe a function prototype I can pass the object name into?
Something more like...
...
List<sObject> stuffToUpdate1 = newList<sObject>();
List<sObject> stuffToUpdate2 = newList<sObject>();
for (Opportunity o : Trigger.new) {
stuffToUpdate1.add(syncRecordTypes('Custom_Object1__c', o));
stuffToUpdate2.add(syncRecordTypes('Custom_Object2__c', o));
}
if (stuffToUpdate1.size() > 0) update stuffToUpdate1;
if (stuffToUpdate2.size() > 0) update stuffToUpdate2;
...
private static List<Object> syncRecordTypes(String sObjName, Opportunity opp) {
// ???
}
apex trigger sobject bestpractice
add a comment |
I have 4 very similar code blocks in a trigger that deal with synchronizing record type changes from Opportunity to its children. The only difference between them is that they do work on different custom objects. Since the actual work they do is identical, it seems like I should be able to combine them using a generic object type but I'm a little fuzzy on how to do it (assuming I even should).
(Note: I'm interested in general best practice here, not how to refactor specific code. Links are acceptable!)
My repetitive code looks something like this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete, after delete) {
if (Trigger.isAfter && Trigger.isUpdate) {
// Get record type map
List<String, Id> rtMap = OpportunityHelper.getRecordTypeMap();
// Update lists
List<Custom_Object1__c> obj1Updates = new List<Custom_Object1__c>();
List<Custom_Object2__c> obj2Updates = new List<Custom_Object1__c>();
// Get object 1 records
List<Custom_Object1__c> obj1List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object1__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Get object 2 records
List<Custom_Object2__c> obj2List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object2__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Map to opportunities
Map<Id, List<Custom_Object1__c>> oppId2Obj1Map = OpportunityHelper.mapify(obj1List);
Map<Id, List<Custom_Object2__c>> oppId2Obj2Map = OpportunityHelper.mapify(obj2List);
for (Opportunity o : Trigger.new) {
// Get record type of opportunity
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
// Get opportunity children
List<Custom_Object1__c> obj1List = oppId2Obj1Map.get(o.Id);
List<Custom_Object2__c> obj2List = oppId2Obj2Map.get(o.Id);
// Sync up obj1 record types
for (Custom_Object1__c obj1 : obj1List) {
// Get record type names of child
String rtObj1 = OpportunityHelper.getRecordTypeName(obj1.RecordTypeId);
// If record types don't match, change the record type of obj1
if (rtOpportunity <> rtObj1) {
obj1.RecordTypeId = rtMap.get(rtOpportunity);
obj1Updates.add(obj1);
}
}
// Sync up obj2 record types
for (Custom_Object2__c obj2 : obj2List) {
// Get record type names of child
String rtObj2 = OpportunityHelper.getRecordTypeName(obj2.RecordTypeId);
// If record types don't match, change the record type of obj2
if (rtOpportunity <> rtObj2) {
obj2.RecordTypeId = rtMap.get(rtOpportunity);
obj2Updates.add(obj2);
}
}
}
// Process record type changes
if (obj1Updates.size() > 0) update obj1Updates;
if (obj2Updates.size() > 0) update obj2Updates;
}
}
So...is there some way I can use a generic object type to minimize my repetitive code here? Maybe a function prototype I can pass the object name into?
Something more like...
...
List<sObject> stuffToUpdate1 = newList<sObject>();
List<sObject> stuffToUpdate2 = newList<sObject>();
for (Opportunity o : Trigger.new) {
stuffToUpdate1.add(syncRecordTypes('Custom_Object1__c', o));
stuffToUpdate2.add(syncRecordTypes('Custom_Object2__c', o));
}
if (stuffToUpdate1.size() > 0) update stuffToUpdate1;
if (stuffToUpdate2.size() > 0) update stuffToUpdate2;
...
private static List<Object> syncRecordTypes(String sObjName, Opportunity opp) {
// ???
}
apex trigger sobject bestpractice
add a comment |
I have 4 very similar code blocks in a trigger that deal with synchronizing record type changes from Opportunity to its children. The only difference between them is that they do work on different custom objects. Since the actual work they do is identical, it seems like I should be able to combine them using a generic object type but I'm a little fuzzy on how to do it (assuming I even should).
(Note: I'm interested in general best practice here, not how to refactor specific code. Links are acceptable!)
My repetitive code looks something like this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete, after delete) {
if (Trigger.isAfter && Trigger.isUpdate) {
// Get record type map
List<String, Id> rtMap = OpportunityHelper.getRecordTypeMap();
// Update lists
List<Custom_Object1__c> obj1Updates = new List<Custom_Object1__c>();
List<Custom_Object2__c> obj2Updates = new List<Custom_Object1__c>();
// Get object 1 records
List<Custom_Object1__c> obj1List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object1__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Get object 2 records
List<Custom_Object2__c> obj2List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object2__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Map to opportunities
Map<Id, List<Custom_Object1__c>> oppId2Obj1Map = OpportunityHelper.mapify(obj1List);
Map<Id, List<Custom_Object2__c>> oppId2Obj2Map = OpportunityHelper.mapify(obj2List);
for (Opportunity o : Trigger.new) {
// Get record type of opportunity
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
// Get opportunity children
List<Custom_Object1__c> obj1List = oppId2Obj1Map.get(o.Id);
List<Custom_Object2__c> obj2List = oppId2Obj2Map.get(o.Id);
// Sync up obj1 record types
for (Custom_Object1__c obj1 : obj1List) {
// Get record type names of child
String rtObj1 = OpportunityHelper.getRecordTypeName(obj1.RecordTypeId);
// If record types don't match, change the record type of obj1
if (rtOpportunity <> rtObj1) {
obj1.RecordTypeId = rtMap.get(rtOpportunity);
obj1Updates.add(obj1);
}
}
// Sync up obj2 record types
for (Custom_Object2__c obj2 : obj2List) {
// Get record type names of child
String rtObj2 = OpportunityHelper.getRecordTypeName(obj2.RecordTypeId);
// If record types don't match, change the record type of obj2
if (rtOpportunity <> rtObj2) {
obj2.RecordTypeId = rtMap.get(rtOpportunity);
obj2Updates.add(obj2);
}
}
}
// Process record type changes
if (obj1Updates.size() > 0) update obj1Updates;
if (obj2Updates.size() > 0) update obj2Updates;
}
}
So...is there some way I can use a generic object type to minimize my repetitive code here? Maybe a function prototype I can pass the object name into?
Something more like...
...
List<sObject> stuffToUpdate1 = newList<sObject>();
List<sObject> stuffToUpdate2 = newList<sObject>();
for (Opportunity o : Trigger.new) {
stuffToUpdate1.add(syncRecordTypes('Custom_Object1__c', o));
stuffToUpdate2.add(syncRecordTypes('Custom_Object2__c', o));
}
if (stuffToUpdate1.size() > 0) update stuffToUpdate1;
if (stuffToUpdate2.size() > 0) update stuffToUpdate2;
...
private static List<Object> syncRecordTypes(String sObjName, Opportunity opp) {
// ???
}
apex trigger sobject bestpractice
I have 4 very similar code blocks in a trigger that deal with synchronizing record type changes from Opportunity to its children. The only difference between them is that they do work on different custom objects. Since the actual work they do is identical, it seems like I should be able to combine them using a generic object type but I'm a little fuzzy on how to do it (assuming I even should).
(Note: I'm interested in general best practice here, not how to refactor specific code. Links are acceptable!)
My repetitive code looks something like this:
trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete, after delete) {
if (Trigger.isAfter && Trigger.isUpdate) {
// Get record type map
List<String, Id> rtMap = OpportunityHelper.getRecordTypeMap();
// Update lists
List<Custom_Object1__c> obj1Updates = new List<Custom_Object1__c>();
List<Custom_Object2__c> obj2Updates = new List<Custom_Object1__c>();
// Get object 1 records
List<Custom_Object1__c> obj1List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object1__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Get object 2 records
List<Custom_Object2__c> obj2List = [
SELECT
Id,
Opportunity__c,
RecordTypeId
FROM Custom_Object2__c
WHERE Opportunity__c IN : Trigger.newMap.keyset()
];
// Map to opportunities
Map<Id, List<Custom_Object1__c>> oppId2Obj1Map = OpportunityHelper.mapify(obj1List);
Map<Id, List<Custom_Object2__c>> oppId2Obj2Map = OpportunityHelper.mapify(obj2List);
for (Opportunity o : Trigger.new) {
// Get record type of opportunity
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
// Get opportunity children
List<Custom_Object1__c> obj1List = oppId2Obj1Map.get(o.Id);
List<Custom_Object2__c> obj2List = oppId2Obj2Map.get(o.Id);
// Sync up obj1 record types
for (Custom_Object1__c obj1 : obj1List) {
// Get record type names of child
String rtObj1 = OpportunityHelper.getRecordTypeName(obj1.RecordTypeId);
// If record types don't match, change the record type of obj1
if (rtOpportunity <> rtObj1) {
obj1.RecordTypeId = rtMap.get(rtOpportunity);
obj1Updates.add(obj1);
}
}
// Sync up obj2 record types
for (Custom_Object2__c obj2 : obj2List) {
// Get record type names of child
String rtObj2 = OpportunityHelper.getRecordTypeName(obj2.RecordTypeId);
// If record types don't match, change the record type of obj2
if (rtOpportunity <> rtObj2) {
obj2.RecordTypeId = rtMap.get(rtOpportunity);
obj2Updates.add(obj2);
}
}
}
// Process record type changes
if (obj1Updates.size() > 0) update obj1Updates;
if (obj2Updates.size() > 0) update obj2Updates;
}
}
So...is there some way I can use a generic object type to minimize my repetitive code here? Maybe a function prototype I can pass the object name into?
Something more like...
...
List<sObject> stuffToUpdate1 = newList<sObject>();
List<sObject> stuffToUpdate2 = newList<sObject>();
for (Opportunity o : Trigger.new) {
stuffToUpdate1.add(syncRecordTypes('Custom_Object1__c', o));
stuffToUpdate2.add(syncRecordTypes('Custom_Object2__c', o));
}
if (stuffToUpdate1.size() > 0) update stuffToUpdate1;
if (stuffToUpdate2.size() > 0) update stuffToUpdate2;
...
private static List<Object> syncRecordTypes(String sObjName, Opportunity opp) {
// ???
}
apex trigger sobject bestpractice
apex trigger sobject bestpractice
asked Jan 11 at 20:50
IxalmidaIxalmida
1355
1355
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .
I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.
So my code will be like:
List<Sobject> genericChildList = new List<Sobject>();
genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
for(Sobject child : genericChildList){
if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
child.put('RecordTypeId',rtMap.get(rtOpportunity));
}
}
update genericChildList;
1
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f246391%2fcombining-similar-code-with-different-objects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .
I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.
So my code will be like:
List<Sobject> genericChildList = new List<Sobject>();
genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
for(Sobject child : genericChildList){
if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
child.put('RecordTypeId',rtMap.get(rtOpportunity));
}
}
update genericChildList;
1
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
add a comment |
You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .
I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.
So my code will be like:
List<Sobject> genericChildList = new List<Sobject>();
genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
for(Sobject child : genericChildList){
if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
child.put('RecordTypeId',rtMap.get(rtOpportunity));
}
}
update genericChildList;
1
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
add a comment |
You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .
I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.
So my code will be like:
List<Sobject> genericChildList = new List<Sobject>();
genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
for(Sobject child : genericChildList){
if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
child.put('RecordTypeId',rtMap.get(rtOpportunity));
}
}
update genericChildList;
You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .
I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.
So my code will be like:
List<Sobject> genericChildList = new List<Sobject>();
genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2
String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
for(Sobject child : genericChildList){
if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
child.put('RecordTypeId',rtMap.get(rtOpportunity));
}
}
update genericChildList;
answered Jan 11 at 21:03
Pranay JaiswalPranay Jaiswal
14.9k32653
14.9k32653
1
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
add a comment |
1
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
1
1
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
Thanks! I figured it would be something easy.
– Ixalmida
Jan 11 at 21:12
add a comment |
Thanks for contributing an answer to Salesforce Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f246391%2fcombining-similar-code-with-different-objects%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown