+ Start a Discussion
Thomas MillerThomas Miller 

Trigger Involving Traversing from Child To Parent's Field

Introduction
Hi everyone and thanks for stopping by! I'd like someone with a bit more knowledge and experience to do their best to asist me here if possible, but I also would like to state I do not want to be spoon fed. Pointing me in the right direction would be the general idea, and maybe a line or 2 of code on specifified sections. As the entire problem will end up being under 10 lines, I would like to be able to solve parts I can once key issues are addressed. Thank you all in advance for your time and contributions!

Problem Description
Write an Apex Trigger so each time a new Review record, API Review__c, is created, the related Media, API Media__c, has its field, API Reviews_Completed__c, incremented by 1.

Other Relevant Information & Thoughts
  • the parent record is API Media__c
  • the child record is API Review__c
  • there is a lookup relationship going from child-Review to parent-Media.
  • Media object has a default 0, number field, API Reviews_Completed__c
  • Ask for any other information if needed!
There are two main points I'm unsure about, so some clarification there is really what I'm looking for, in addition to the only lines of code I want. First, the part where I use __r to, at least I think, grab the id of the parent-Media record. I'm doing that because I want to use it for my SOQL query later on, the id = :recId part, but I'm not 100% sure it's correctly grabbing the Media recId for later use. The second part I'm unsure about is how I'm meant to access the Reviews_Completed__c field. This goes into the idea of taking a list and breaking it down into single objects to access their fields, which I thought I had done before without any problem. I'm not sure if my SOQL query should be a list of <Media__c> type, or a single Media__c sObject variable. If i can just do LIMIT 1, since the only record that matters is the one I'm currently saving and about to allow insertation, then I would think I don't need a list, in which case I should be able to increment it by simply doing sObject.FieldToIncrement++; My code is below and includes the list based case since I've explained the other way I had imagined it may work. Neither are working. Again, any help is much appreciated!

Code (gives index out of bounds error - System.QueryException: List has no rows for assignment to SObject - on SOQL query below)
As far as the error goes, I figure it's because the query gives the id field in addition to what I'm asking for, but if a list is required, please explain how I then go about taking that object out of the list in order to access the object's Reviews_Completed__c API to increment it.
trigger testTrig on Review__c (before insert) {
	
	// Following should also check every Review__c object r, in Trigger.New, and
	// if the API Review_Submission_Date__c API is empty, put the current date - this part works
    // This portion wasn't mentioned above but it's in my code as part of the exercise I'm working on.

    //To hold Media sObj rec ids
	List<Id> recId = new List<Id>();

// Loop to both add all Media ids to a list as well as change a blank submission date to today's date.
	for (Review__c r : Trigger.New) {
        recId.add(r.Media__r.id);
        if (r.Review_Submission_Date__c == null)
			r.Review_Submission_Date__c = Date.today();
    }
    
// Now that all Media ids are listed, query for 1 record such that the query result is
// of Media type and has an id that is also part of Trigger.New, meaning in list recId
// The only needed field is Reviews_Completed__c, which is going to be incremented by 1
// for each (API) Review__c record creation.
    Media__c m = [SELECT id, Reviews_Completed__c FROM Media__c
                  WHERE id IN :recId LIMIT 1];
    m.Reviews_Completed__c++;
    insert m;
    
}

Best,
Tom



 
Best Answer chosen by Thomas Miller
Thomas MillerThomas Miller
Finally solved with the following new code:

trigger testTrig on Review__c (before insert) {
    /*
     * The objective of this Trigger is to modify a Review record just
     * prior to insert and 1) change a blank date to today's date and
     * 2) update the parent Media record's Reviews_Completed field
     * to 1 higher than its current value.
     */
    
    //Create list of type Id to hold ids of Review obj parent record
    List<Id> id = new List<Id>();
    
    //Iterate through all Review obj within trigger
    for (Review__c r : Trigger.New) {
        
        //Add the Media__c field, the id of the parent, of each Review__c in trigger to list
        id.add(r.Media__c);
        
        // Assign today's date to the Review__c obj in the trigger
        // If the Review Submission Date field is empty, assign today's date
        if (r.Review_Submission_Date__c == null)
            r.Review_Submission_Date__c = Date.today();
    }
    
    //Query for the desired Media records where the id of the
    //record found matches the id of the records in the trigger, and our list
    List<Media__c> m = [SELECT Reviews_Completed__c FROM Media__c WHERE id = :id];
    
    //Increment field of the only Media obj in our list, thus index 0, and update the record
    m[0].Reviews_Completed__c++;
    update m;
}

:)

Best,
Tom

All Answers

11c-at-sfdc11c-at-sfdc
Hi Tom, a quick clarification. Every record that comes to the trigger will have a corresponding Media__c record for which Reviews_Completed__c field needs to get incremented, correct? In other words, as soon as a review record causes your trigger to fire, simply increment the Reviews_Completed__c field in the related parent Media__c record, right?
Thomas MillerThomas Miller
Yes Avi, that is correct. There is a custom lookup field, Media__c, on every Review__c that sets the relationship for the record coming to the trigger as to which Media__c object it will lookup to. That corresponding Media__c object then needs its Reviews_Completed__c field incremented by 1. In my understanding, you can't query for that though because it wouldn't be in the DB yet, since it's a before insert type trigger, right? I am aware how trivial this problem is, but there's some concept or some syntax I'm missing from my limited approach.
11c-at-sfdc11c-at-sfdc
Hi Tom,
Why wouldn't you do after Review__c insert so that you can get hold of Media__c Ids? I think the following code should work. Please select as the best answer if this helped.
trigger testTrig on Review__c (after insert) {
    //Create a set for IDs for Media__c objects related to Review__c
    Set<ID> MediaIds = new Set<ID>();

    //Iterate through Reviews__c being inserted
    for (Review__c r : trigger.new){
        MediaIds.add(r.Media__r.Id);
    }

    //Use SOQL to extract related Media__c records
    List<Media__c> media = [select id, Reviews_Completed__c from Media__c where id in : MediaIds];

    //Loop over the media__c records to increment the Reviews_Completed__c field
    for (Media__c m: media){
        //update the Reviews_Completed__c field
        m.Reviews_Completed__c++;
    }    

    //finally, update all media records
    //check for errors..etc.
    update media;
}

 
Thomas MillerThomas Miller
Finally solved with the following new code:

trigger testTrig on Review__c (before insert) {
    /*
     * The objective of this Trigger is to modify a Review record just
     * prior to insert and 1) change a blank date to today's date and
     * 2) update the parent Media record's Reviews_Completed field
     * to 1 higher than its current value.
     */
    
    //Create list of type Id to hold ids of Review obj parent record
    List<Id> id = new List<Id>();
    
    //Iterate through all Review obj within trigger
    for (Review__c r : Trigger.New) {
        
        //Add the Media__c field, the id of the parent, of each Review__c in trigger to list
        id.add(r.Media__c);
        
        // Assign today's date to the Review__c obj in the trigger
        // If the Review Submission Date field is empty, assign today's date
        if (r.Review_Submission_Date__c == null)
            r.Review_Submission_Date__c = Date.today();
    }
    
    //Query for the desired Media records where the id of the
    //record found matches the id of the records in the trigger, and our list
    List<Media__c> m = [SELECT Reviews_Completed__c FROM Media__c WHERE id = :id];
    
    //Increment field of the only Media obj in our list, thus index 0, and update the record
    m[0].Reviews_Completed__c++;
    update m;
}

:)

Best,
Tom
This was selected as the best answer
ikle aseaikle asea
You can try to use the above script with your blog just like I did with my reviews blog (https://www.soundboxlab.com/).