Pregunta

Estoy tratando de aprender el lenguaje de programación Apex de Salesforce.com y tengo un ejemplo de algún código aquí que proviene del libro "Desarrollo con la plataforma Force.com" de Jason Ouellette. Todavía estoy aprendiendo los conceptos básicos, así que por favor tengan paciencia conmigo. Para poner este código en contexto, hay una aplicación de muestra de Services Manager que va a lo largo del libro y estoy examinando un dispositivo de activación APEX que han escrito que se supone que se asegura de que las informes de tiempo tengan una tarea válida. Una tarea es un registro que indica que un recurso cuenta con personal en un proyecto durante un cierto período de tiempo. Un consultor (también conocido como recurso) puede ingresar a una tarjeta de tiempo solo para un proyecto y un período de tiempo que está autorizado para trabajar. Resource_c es un padre para los objetos Tailment_C y TimeCard_C.

Así que aquí está el código que me dan para el disparador y la clase APEX correspondiente. He estado intentando desglosarlo y comentar/Preguntar en su línea por línea para dar sentido a su lógica. Sin embargo, todavía me falta algunos fundamentos aquí, no dude en ayudarme a descifrar esto.

5-57 el gatillo

trigger validateTimecard on Timecard__c (before insert, before update) {
    TimecardManager.handleTimecardChange(Trigger.old, Trigger.new);  
    // TheApexClass.methodThatDoesWork(variable, variable)  
    // So there are 2 parameters which are 2 lists, Trigger.old and Trigger.new.  
    // Which means, when this method is called it needs these 2 lists 
    // to process it's block of code, right?
    // Why are they called Trigger.old, Trigger.new?  Does the order of variables          matter?  
}

5-58 - La clase APEX, que realiza el trabajo de validar la tarjeta de tiempo en nombre del disparador.

   public class TimecardManager {
        public class TimecardException extends Exception {}
        public static void handleTimecardChange(List<Timecard__c> oldTimecards, List<Timecard__c> newTimecards) { 

            // Identifying 2 lists of Timecards as parameters, oldTimecards and newTimecards
            // within the class.  How is this associated with the trigger parameters 
            // that were seen in the trigger above.  Are they the same parameters with 
            // different names?  Why are they named differently here?  Is it better to
            // write the trigger first, or the apex class first?

            Set<ID> resourceIds = new Set<ID>();  // making a new set of primitive data type ID called resourceIds

            for (Timecard__c timecard : newTimecards) {  
                // This for loop assigns the timecard variable record to the list of newTimecards
                // and then executes the block of code below for each.
                // The purpose of this is to identify all the resources that have timecards.
                resourceIds.add(timecard.Resource__c); 

                // It does this by adding the Timecard_c's relationship ID from each parent record Resource_c to the resourceIds set.  
                // For clarification, Resource_c is a parent to both 
                // Assignment_c and Timecard_c objects. Within the Timecard_c object, Resource_c
                // is a Master-Detail data type.  Is there a relationship ID that is created 
                // for the relationship between Resource_c and Timecard_c?  
            }

            List<Assignment__c> assignments = [ SELECT Id, Start_Date__c, End_Date__c, Resource__c FROM Assignment__c WHERE Resource__c IN :resourceIds ];

            // The purpose of this is to make a list of selected information from Assignments_c that have resources with timecards. 

            if (assignments.size() == 0) {  
                // If there isn't a Resource_c from Assignments_c that matches a Resource_c that has a Timecard_c,
                throw new TimecardException('No assignments');  // then an exception is thrown.
            }

            Boolean hasAssignment;  // creation of a new Boolean variable
            for (Timecard__c timecard : newTimecards) {  // so for every newTimecards records,
                hasAssignment = false; // set Boolean to false as default,
                for (Assignment__c assignment : assignments) {  // check through the assignments list 
                    if (assignment.Resource__c == timecard.Resource__c &&  // to make sure the Resources match,
                        timecard.Week_Ending__c - 6 >= assignment.Start_Date__c && // the end of the timecard is greater than the assignment's start date, 
                        timecard.Week_Ending__c <= assignment.End_Date__c) { // and the end of the timecard is before the assignment's end date.
                            hasAssignment = true;  //  if these all 3 are correct, than the Timecard does in fact have an assignment.
                            break; // exits the loop
                    }
                }
                if (!hasAssignment) {  // if hasAssignment is false then,
                    timecard.addError('No assignment for resource ' + // display an error message
                    timecard.Resource__c + ', week ending ' + 
                    timecard.Week_Ending__c);
                }
            }
        }
    }

Gracias por tu ayuda.

¿Fue útil?

Solución

1. ¿Qué es Trigger.old/Trigger.Neo :?

Trigger.new/trigger.old son colecciones estáticas disponibles para cualquier código APEX que se ejecute en el contexto de disparo, es decir, disparando directamente en el disparador o en cualquier clase llamada por disparo.

APEX incluso le da disparador.newmap y trigger.oldmap, que devuelve un mapa en lugar de la lista de SOBject.

El único propósito de estas colecciones depende en qué evento se dispara el disparador, por ejemplo, si el evento es "antes de insertar" o "después de insertar" el activador. Trigger.old siempre se usa para comparar los cambios realizados durante las actualizaciones de registros.

2. El orden es importante: Solo depende de su lógica, en este caso del administrador de la tarjeta de tiempo, ya que el método "HandletimecardChange" espera viejas tarjetas de tiempo antes de nuevas, por lo que debe pasar Trigger.old como primer argumento.

3. ¿Debe ser enumerable? : Nuevamente, depende de su implementación, Trigger.new/old devuelve una lista donde Sobject es en el que se escribe el disparador. Tampoco es obligatorio pasar el activador. Hace que las pruebas unitarias sean más fáciles.

Espero que esto ayude, lea primero la referencia del lenguaje Apex para una comprensión más profunda sobre el lenguaje APEX en general. El libro de Jason O. es increíble, pero primero debes entender los conceptos básicos. Aquí está el enlace a la referencia del idioma Apex: http://www.salesforce.com/us/developer/docs/apexcode/index.htm

Otros consejos

Gatillo new, newMap, old y oldMap Solo están disponibles dependiendo del tipo de DML que esté rastreando.

Eliminar = Solo viejo está disponible

Insert = solo nuevo está disponible

UPDATY = Tanto los viejos como los nuevos están disponibles y el orden de las entradas en las listas coincide (por ejemplo, nuevo [1] reemplaza a los viejos [1]). nuevos contienen nuevos valores, antiguo contiene valores antiguos (pero la identificación siempre es la misma) para que pueda comparar y verificar si se cambia un determinado archivado.

Siempre debe tratar las nuevas/viejas como listas de entrada múltiple (o mapas para *mapa). Nunca asuma que solo habrá una entrada, ya que con la operación regular de actualización de SQL, solo invocará un desencadenante una vez que le brinde una lista de filas antiguas y nuevas. Tienes que iterar a través de todas las filas cambiadas y aplicar cualquier lógica que tenga.

En este ejemplo, el parámetro Oldtimecards no se está utilizando en absoluto en el método estático, por lo tanto, tampoco era necesario referirse en absoluto. Con toda probabilidad, también desperdició recursos ya que SF tuvo que construir una lista completa sin siquiera usarla (sin embargo, no estoy seguro de si lo optimizan en absoluto). Dado que controla el código de activación y el código de clase de soporte pasan solo lo que necesita.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top