Skip to main content
ƚnase a nosotros en TDX, San Francisco o en Salesforce+ del 5 al 6 de marzo en la conferencia de desarrolladores para la era del agente de la IA. Regƭstrese ahora.

InformaciĆ³n general sobre desencadenadores de Apex

Objetivos de aprendizaje

DespuƩs de completar esta unidad, podrƔ hacer lo siguiente:

  • Escribir un desencadenador para un objeto de Salesforce.
  • Utilizar variables de contexto de desencadenadores.
  • Llamar a un mĆ©todo de clase desde un desencadenador.
  • Usar el mĆ©todo addError() de sObject en un desencadenador para restringir las operaciones de guardado.
Nota

Nota

ĀæEs su idioma de aprendizaje espaƱol (LATAM)? Comience el reto en un Trailhead Playground en espaƱol (LATAM) y copie y pegue los valores en espaƱol (LATAM). Si no aprueba el reto en su organizaciĆ³n en espaƱol (LATAM), recomendamos que (1) cambie la configuraciĆ³n local a Estados Unidos, (2) cambie el idioma a inglĆ©s (segĆŗn estas instrucciones) y, luego, (3) haga clic en el botĆ³n ā€œCheck Challengeā€ (Comprobar el reto) nuevamente.

Consulte la insignia Trailhead en su idioma para obtener mĆ”s informaciĆ³n sobre cĆ³mo aprovechar la experiencia de Trailhead en otros idiomas.

Antes de comenzar

Los desencadenadores de Apex son Ćŗtiles, divertidos y geniales. Si bien este mĆ³dulo lo ayuda a empezar a utilizarlos, tambiĆ©n hace referencia a otras funciones de Salesforce para mostrarle el poder de los desencadenadores de Apex. Para aprovechar al mĆ”ximo este mĆ³dulo, le recomendamos que consulte primero estos mĆ³dulos:

Escritura de desencadenadores de Apex

Los desencadenadores de Apex permiten realizar acciones personalizadas antes o despuĆ©s de eventos para registros en Salesforce, como inserciones, actualizaciones o eliminaciones. Del mismo modo que los sistemas de bases de datos admiten desencadenadores, Apex permite el uso de desencadenadores para la gestiĆ³n de registros.

Normalmente, los desencadenadores se usan para realizar operaciones basadas en condiciones especĆ­ficas, modificar registros relacionados o impedir determinadas operaciones. Puede usar desencadenadores para realizar cualquier operaciĆ³n admitida en Apex, lo que incluye la ejecuciĆ³n de SOQL y DML o la llamada a mĆ©todos Apex personalizados.

Use desencadenadores para realizar tareas que no se pueden realizar con herramientas interactivas (apuntar y hacer clic) en la interfaz de usuario de Salesforce. Por ejemplo, si se valida el valor de un campo o se actualiza un campo en un registro, utilice flujos y reglas de validaciĆ³n. Use desencadenadores de Apex si el desempeƱo y la escala son importantes, si su lĆ³gica es demasiado compleja para las herramientas interactivas o si estĆ” ejecutando operaciones con gran consumo de CPU.

Se pueden definir desencadenadores para objetos estƔndar de nivel superior, como una cuenta o un contacto, objetos personalizados y determinados objetos secundarios estƔndar. Los desencadenadores se activan de forma predeterminada al crearlos. Salesforce activa automƔticamente desencadenadores cuando se producen eventos de base de datos especƭficos.

Sintaxis de desencadenadores

La sintaxis de una definiciĆ³n de desencadenador es distinta de la sintaxis de una definiciĆ³n de clase. La definiciĆ³n de un desencadenador empieza por la palabra clave trigger. A continuaciĆ³n, le siguen el nombre del desencadenador, el objeto de Salesforce con el que estĆ” asociado el desencadenador y las condiciones en las que este se activa. Un desencadenador tiene la siguiente sintaxis:

trigger TriggerName on ObjectName (trigger_events) {
   code_block
}

Para ejecutar un desencadenador antes o despuĆ©s de operaciones de inserciĆ³n, actualizaciĆ³n, eliminaciĆ³n y recuperaciĆ³n, especifique varios eventos de desencadenador en una lista separada por comas. Los eventos que se pueden especificar son:

  • before insert (antes de insertar)
  • before update (antes de actualizar)
  • before delete (antes de eliminar)
  • after insert (despuĆ©s de insertar)
  • after update (despuĆ©s de actualizar)
  • after delete (despuĆ©s de eliminar)
  • after undelete (despuĆ©s de recuperar)

Ejemplo de desencadenador

Este desencadenador sencillo se activa antes de insertar una cuenta y escribe un mensaje en el registro de depuraciĆ³n.

  1. En Developer Console, haga clic en File (Archivo) | New (Nuevo) | Apex Trigger (Desencadenador de Apex).
  2. Ingrese HelloWorldTrigger como nombre del desencadenador y, a continuaciĆ³n, seleccione la cuenta para sObject. Haga clic en Enviar.
  3. Sustituya el cĆ³digo predeterminado por lo siguiente:


    trigger HelloWorldTrigger on Account (before insert) {
    	System.debug('Hello World!');
    }
  4. Para guardar, pulse Ctrl+S.
  5. Para probar el desencadenador, cree una cuenta.
    1. Haga clic en Debug (Depurar) | Open Execute Anonymous Window (Abrir ventana de ejecuciĆ³n anĆ³nima).
    2. En la ventana nueva, agregue lo siguiente y, a continuaciĆ³n, haga clic en Execute (Ejecutar).


      Account a = new Account(Name='Test Trigger');
      insert a;
  1. En el registro de depuraciĆ³n, busque la declaraciĆ³n Hello World!. En el registro se muestra ademĆ”s que el desencadenador se ha ejecutado.

Tipos de desencadenadores

Hay dos tipos de desencadenadores.

  • Los desencadenadores previos se usan para actualizar o validar valores de registro antes de guardarlos en la base de datos.
  • Los desencadenadores posteriores se usan para acceder a los valores de campo establecidos por el sistema (por ejemplo, campo Id o LastModifiedDate de un registro) y aplicar cambios a otros registros. Los registros que activan el desencadenador posterior son de solo lectura.

Uso de variables de contexto

Para acceder a los registros que activan el desencadenador, use variables de contexto. Por ejemplo, Trigger.New contiene todos los registros insertados en desencadenadores de inserciĆ³n o actualizaciĆ³n. Trigger.Old proporciona la versiĆ³n anterior de sObjects antes de actualizarlos en desencadenadores de actualizaciĆ³n o una lista de sObjects eliminados en desencadenadores de eliminaciĆ³n. Los desencadenadores se pueden activar cuando se inserta un registro o cuando se insertan numerosos registros de forma masiva mediante la API o Apex. Por consiguiente, las variables de contexto, como Trigger.New, pueden contener solo un registro o varios registros. Puede iterar en Trigger.New para obtener cada sObject individual.

Este ejemplo es una versiĆ³n modificada del desencadenador de ejemplo HelloWorldTrigger. Itera en cada cuenta mediante un bucle for y actualiza el campo DescripciĆ³n en cada caso.

trigger HelloWorldTrigger on Account (before insert) {
    for(Account a : Trigger.new) {
        a.Description = 'New description';
    }
}
Nota

El sistema guarda los registros que han activado el desencadenador previo una vez que el desencadenador finaliza la ejecuciĆ³n. Puede modificar los registros en el desencadenador sin llamar de forma explĆ­cita a una operaciĆ³n de inserciĆ³n o actualizaciĆ³n de DML. Si realiza declaraciones DML en estos registros, obtiene un error.

Algunas otras variables de contexto devuelven un valor booleano para indicar si el desencadenador se ha activado debido a una actualizaciĆ³n o a algĆŗn otro evento. Estas variables son de utilidad cuando un desencadenador combina varios eventos. Por ejemplo:

trigger ContextExampleTrigger on Account (before insert, after insert, after delete) {
    if (Trigger.isInsert) {
        if (Trigger.isBefore) {
            // Process before insert
        } else if (Trigger.isAfter) {
            // Process after insert
        }
    }
    else if (Trigger.isDelete) {
        // Process after delete
    }
}

La tabla siguiente es una lista de todas las variables de contexto para desencadenadores.

Variable

Uso

isExecuting

Devuelve true si el contexto actual para el cĆ³digo Apex es un desencadenador, pero no una pĆ”gina de Visualforce, un servicio web o una llamada a API executeanonymous().

isInsert

Devuelve true si este desencadenador se activĆ³ debido a una operaciĆ³n de inserciĆ³n en la interfaz de usuario de Salesforce, Apex o la API.

isUpdate

Devuelve true si este desencadenador se activĆ³ debido a una operaciĆ³n de actualizaciĆ³n en la interfaz de usuario de Salesforce, Apex o la API.

isDelete

Devuelve true si este desencadenador se activĆ³ debido a una operaciĆ³n de eliminaciĆ³n en la interfaz de usuario de Salesforce, Apex o la API.

isBefore

Devuelve true si este desencadenador se ha activado antes de que se haya guardado cualquier registro.

isAfter

Devuelve true si este desencadenador se ha activado despuƩs de que se hayan guardado todos los registros.

isUndelete

Devuelve true si este desencadenador se ha activado despuĆ©s de recuperar un registro desde la papelera. Esta recuperaciĆ³n puede producirse despuĆ©s de una operaciĆ³n de recuperaciĆ³n desde la interfaz de usuario de Salesforce, Apex o la API.

new

Devuelve una lista de versiones nuevas de registros de sObject.

Esta lista de sObject solamente estĆ” disponible en desencadenadores insert, update y undelete, y los registros Ćŗnicamente se pueden modificar en desencadenadores before.

newMap

AsignaciĆ³n de Id. a las versiones nuevas de los registros de sObject.

Esta asignaciĆ³n solo estĆ” disponible en los desencadenadores before update, after insert, after update y after undelete.

old

Devuelve una lista de versiones anteriores de registros de sObject.

Esta lista de sObjects solo estĆ” disponible en los desencadenadores update y delete.

oldMap

AsignaciĆ³n de Id. a las versiones anteriores de los registros de sObject.

Esta asignaciĆ³n solo estĆ” disponible en los desencadenadores update y delete.

operationType

Devuelve una enumeraciĆ³n de tipo System.TriggerOperation correspondiente a la operaciĆ³n actual.

Los posibles valores de la enumeraciĆ³n System.TriggerOperation son los siguientes: BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE,AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE y AFTER_UNDELETE. Si varĆ­a su lĆ³gica de programaciĆ³n basĆ”ndose en diferentes tipos de desencadenadores, considere el uso de la declaraciĆ³n switch con diferentes combinaciones de estados de enumeraciĆ³n de ejecuciĆ³n de desencadenador Ćŗnicos.

size

NĆŗmero total de registros en una invocaciĆ³n de desencadenadores (tanto anteriores como nuevos).

Llamada a un mƩtodo de clase desde un desencadenador

Puede llamar a mĆ©todos de utilidad pĆŗblicos desde un desencadenador. La llamada a mĆ©todos de otras clases permite la reutilizaciĆ³n de cĆ³digo, reduce el tamaƱo de los desencadenadores y mejora el mantenimiento del cĆ³digo Apex. AdemĆ”s, permite el uso de programaciĆ³n orientada a los objetos.

En el siguiente ejemplo de desencadenador se muestra cĆ³mo llamar a un mĆ©todo estĆ”tico desde un desencadenador. Si el desencadenador se ha activado debido a un evento de inserciĆ³n, en el ejemplo se llama al mĆ©todo estĆ”tico sendMail() de la clase EmailManager. Este mĆ©todo de utilidad envĆ­a un email al destinatario especificado y contiene el nĆŗmero de registros de contacto insertados.

  1. En Developer Console, haga clic en Archivo | Nuevo | Clase de Apex.
  2. Ingrese EmailManager y haga clic en OK (Aceptar).
  3. Sustituya el cuerpo de clase predeterminado por el ejemplo de clase EmailManager que se muestra a continuaciĆ³n.
    public class EmailManager {
        // Public method
        public static void sendMail(String address, String subject, String body) {
            // Create an email message object
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            String[] toAddresses = new String[] {address};
            mail.setToAddresses(toAddresses);
            mail.setSubject(subject);
            mail.setPlainTextBody(body);
            // Pass this email message to the built-in sendEmail method
            // of the Messaging class
            Messaging.SendEmailResult[] results = Messaging.sendEmail(
                                      new Messaging.SingleEmailMessage[] { mail });
            // Call a helper method to inspect the returned results
            inspectResults(results);
        }
        // Helper method
        private static Boolean inspectResults(Messaging.SendEmailResult[] results) {
            Boolean sendResult = true;
            // sendEmail returns an array of result objects.
            // Iterate through the list to inspect results.
            // In this class, the methods send only one email,
            // so we should have only one result.
            for (Messaging.SendEmailResult res : results) {
                if (res.isSuccess()) {
                    System.debug('Email sent successfully');
                }
                else {
                    sendResult = false;
                    System.debug('The following errors occurred: ' + res.getErrors());
                }
            }
            return sendResult;
        }
    }
  4. En Developer Console, haga clic en File (Archivo) | New (Nuevo) | Apex Trigger (Desencadenador de Apex).
  5. Ingrese ExampleTrigger como nombre del desencadenador y, a continuaciĆ³n, seleccione Contact (Contacto) para sObject. Haga clic en Enviar.
  6. Sustituya el cĆ³digo predeterminado por lo siguiente y, a continuaciĆ³n, modifique el texto del marcador de posiciĆ³n de email sendMail() con su direcciĆ³n de email.
    trigger ExampleTrigger on Contact (after insert, after delete) {
        if (Trigger.isInsert) {
            Integer recordCount = Trigger.new.size();
            // Call a utility method from another class
            EmailManager.sendMail('Your email address', 'Trailhead Trigger Tutorial',
                        recordCount + ' contact(s) were inserted.');
        }
        else if (Trigger.isDelete) {
            // Process after delete
        }
    }
  7. Para guardar, pulse Ctrl+S.
  8. Para probar el desencadenador, cree un contacto.
    1. Haga clic en Debug (Depurar) | Open Execute Anonymous Window (Abrir ventana de ejecuciĆ³n anĆ³nima).
    2. En la ventana nueva, agregue lo siguiente y, a continuaciĆ³n, haga clic en Execute (Ejecutar).
      Contact c = new Contact(LastName='Test Contact');
      insert c;
  1. En el registro de depuraciĆ³n, compruebe si el desencadenador se ha activado. Al final del registro, busque el mensaje de depuraciĆ³n escrito mediante el mĆ©todo de utilidad: DEBUG|Email sent successfully
  2. A continuaciĆ³n, compruebe si recibiĆ³ un email con el texto de cuerpo 1 contact(s) were inserted (Se insertĆ³ 1 contacto).

    Con el nuevo desencadenador, recibirĆ” un email cada vez que agregue uno o varios contactos.

Los desencadenadores se suelen usar para gestionar y acceder a registros relacionados con otros registros en el contexto del desencadenador (registros que activan el desencadenador).

Este desencadenador agrega una oportunidad relacionada para cada cuenta nueva o actualizada si no hay ninguna oportunidad asociada a la cuenta. El desencadenador realiza primero una consulta SOQL para obtener todas las oportunidades secundarias de las cuentas en las que se ha activado el desencadenador. A continuaciĆ³n, el desencadenador itera en la lista de sObjects en Trigger.New para obtener el sObject de cada cuenta. Si la cuenta no tiene ningĆŗn sObject de oportunidad relacionado, el bucle (for) crea uno. Si el desencadenador ha creado oportunidades, la declaraciĆ³n final las inserta.

  1. Agregue el siguiente desencadenador mediante Developer Console (realice los pasos del ejemplo de HelloWorldTrigger, pero use AddRelatedRecord como nombre del desencadenador).
    trigger AddRelatedRecord on Account(after insert, after update) {
        List<Opportunity> oppList = new List<Opportunity>();
        // Get the related opportunities for the accounts in this trigger
        Map<Id,Account> acctsWithOpps = new Map<Id,Account>(
            [SELECT Id,(SELECT Id FROM Opportunities) FROM Account WHERE Id IN :Trigger.new]);
        // Add an opportunity for each account if it doesn't already have one.
        // Iterate through each account.
        for(Account a : Trigger.new) {
            System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size());
            // Check if the account already has a related opportunity.
            if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) {
                // If it doesn't, add a default opportunity
                oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
                                           StageName='Prospecting',
                                           CloseDate=System.today().addMonths(1),
                                           AccountId=a.Id));
            }
        }
        if (oppList.size() > 0) {
            insert oppList;
        }
    }
  2. Para probar el desencadenador, cree una cuenta en la interfaz de usuario de Salesforce y asĆ­gnele el nombre Apples & Oranges (Manzanas y naranjas).
  3. En la lista relacionada de oportunidades de la pƔgina de la cuenta, busque la oportunidad nueva. El desencadenador ha agregado esta oportunidad automƔticamente.
Nota

El desencadenador que ha agregado itera en todos los registros que forman parte del contexto del desencadenador (el bucle for itera en Trigger.New). No obstante, el bucle de este desencadenador podrĆ­a ser mĆ”s eficiente. En realidad no es necesario acceder a cada cuenta en el contexto de este desencadenador, sino solo a un subconjunto (cuentas sin oportunidades). En la siguiente unidad se describe cĆ³mo aumentar la eficiencia de este desencadenador. En la unidad Patrones de diseƱo de desencadenadores masivos, puede obtener informaciĆ³n sobre cĆ³mo modificar la consulta SOQL para obtener solamente cuentas sin oportunidades. A continuaciĆ³n, puede aprender a iterar solamente en esos registros.

Uso de excepciones de desencadenadores

En ocasiones, es posible que necesite agregar restricciones para determinadas operaciones de base de datos, como impedir que los registros se guarden cuando se cumplen determinadas condiciones. Para evitar que los registros se guarden en un desencadenador, llame al mĆ©todo addError() del sObject en cuestiĆ³n. El mĆ©todo addError() genera un error grave en el desencadenador. El mensaje de error se muestra en la interfaz de usuario y se registra.

El siguiente desencadenador impide la eliminaciĆ³n de una cuenta si esta tiene oportunidades relacionadas. De forma predeterminada, la eliminaciĆ³n de una cuenta provoca la eliminaciĆ³n en cascada de todos sus registros relacionados. Este desencadenador impide la eliminaciĆ³n en cascada de las oportunidades. Pruebe este desencadenador. Si ha ejecutado el ejemplo anterior, su organizaciĆ³n tiene una cuenta llamada Apples & Oranges con una oportunidad relacionada. En este ejemplo se usa dicha cuenta.

  1. Use Developer Console para agregar el siguiente desencadenador.
    trigger AccountDeletion on Account (before delete) {
        // Prevent the deletion of accounts if they have related opportunities.
        for (Account a : [SELECT Id FROM Account
                         WHERE Id IN (SELECT AccountId FROM Opportunity) AND
                         Id IN :Trigger.old]) {
            Trigger.oldMap.get(a.Id).addError(
                'Cannot delete account with related opportunities.');
        }
    }
  2. En la interfaz de usuario de Salesforce, navegue hasta la pƔgina de la cuenta Apples & Oranges (Manzanas y naranjas) y haga clic en Delete (Eliminar).
  3. En la ventana emergente de confirmaciĆ³n, haga clic en OK (Aceptar).

    Busque el error de validaciĆ³n con el mensaje de error personalizado Cannot delete account with related opportunities (No se puede eliminar la cuenta con oportunidades relacionadas).

  4. Desactive el desencadenador AccountDeletion. Si deja este desencadenador activado, no podrĆ” revisar los aspectos complejos.
    1. En Setup (ConfiguraciĆ³n), busque Apex Triggers (Desencadenadores de Apex).
    2. En la pƔgina Desencadenadores de Apex, haga clic en Edit (Modificar) junto al desencadenador AccountDeletion.
    3. Anule la selecciĆ³n de EstĆ” activo (Is Active).
    4. Haga clic en Save (Guardar).
Nota

La llamada a addError() en un desencadenador revierte todo el conjunto de operaciones, excepto si se llama a DML masivo con una validez parcial.

  • Si una llamada a DML masivo en la API de Plataforma Lightning ha generado el desencadenador, el motor en tiempo de ejecuciĆ³n prescinde de los registros incorrectos. A continuaciĆ³n, el motor en tiempo de ejecuciĆ³n intenta el almacenamiento parcial de los registros que no han generado errores.
  • Si una declaraciĆ³n DML en Apex ha generado el desencadenador, cualquier error revierte toda la operaciĆ³n. No obstante, el motor en tiempo de ejecuciĆ³n sigue procesando cada registro de la operaciĆ³n para compilar una lista de errores exhaustiva.

Desencadenadores y llamadas

Apex permite hacer llamadas e integrar el cĆ³digo Apex con servicios web externos. Estos contactos de Apex con servicios web externos se denominan llamadas. Por ejemplo, puede hacer una llamada a un servicio de cotizaciĆ³n para conocer las Ćŗltimas cotizaciones. Al hacer una llamada desde un desencadenador, dicha llamada se debe hacer de forma asĆ­ncrona para que el proceso del desencadenador no le impida trabajar mientras espera la respuesta del servicio externo. La llamada asĆ­ncrona se realiza mediante un proceso en segundo plano y la respuesta se recibe cuando el servicio externo la devuelve.

Para hacer una llamada desde un desencadenador, llame a un mƩtodo de clase que se ejecute de forma asƭncrona. Este mƩtodo se llama mƩtodo futuro y se anota con @future(callout=true). Esta clase de ejemplo contiene el mƩtodo futuro que hace la llamada.

Nota

En el ejemplo se usa una direcciĆ³n URL de extremo hipotĆ©tica con fines ilustrativos. No puede ejecutar este ejemplo a menos que cambie el extremo a una URL vĆ”lida y agregue un sitio remoto en Salesforce para su extremo.

public class CalloutClass {
    @future(callout=true)
    public static void makeCallout() {
        HttpRequest request = new HttpRequest();
        // Set the endpoint URL.
        String endpoint = 'http://yourHost/yourService';
        request.setEndPoint(endpoint);
        // Set the HTTP verb to GET.
        request.setMethod('GET');
        // Send the HTTP request and get the response.
        HttpResponse response = new HTTP().send(request);
    }
}

En este ejemplo se muestra el desencadenador que llama al mƩtodo en la clase para hacer una llamada asƭncrona.

trigger CalloutTrigger on Account (before insert, before update) {
    CalloutClass.makeCallout();
}

Esta secciĆ³n es solo una descripciĆ³n general de las llamadas y el objetivo no es proporcionar informaciĆ³n detallada. Para obtener mĆ”s informaciĆ³n, consulte InvocaciĆ³n de llamadas utilizando Apex en la GuĆ­a del desarrollador de Apex.

Recursos

Reto prƔctico

+500 puntos

Prepararse

CompletarĆ” esta/este unidad en su propia organizaciĆ³n de prĆ”cticas. Haga clic en Iniciar para empezar a trabajar, o haga clic en el nombre de su organizaciĆ³n para seleccionar una diferente.

Su reto

Crear un Apex trigger

Cree un Apex trigger que establezca el cĆ³digo postal de envĆ­o de una cuenta de modo que coincida con el cĆ³digo postal de facturaciĆ³n si se selecciona la opciĆ³n Coincidencia con direcciĆ³n de facturaciĆ³n. Active el desencadenador antes de insertar o actualizar una cuenta.

Trabajo previo:
Agregue un campo con una casilla de verificaciĆ³n en el objeto Cuenta:

  • Etiqueta de campo: Coincidencia con direcciĆ³n de facturaciĆ³n
  • Nombre del campo: Match_Billing_Address
    / Nota: El nombre de API resultante debe ser Match_Billing_Address__c.

  • Cree un Apex trigger:
    • Name: AccountAddressTrigger
    • Object: Account
    • Eventos: before insert y before update
    • CondiciĆ³n: Coincidencia con direcciĆ³n de facturaciĆ³n verdadero
    • OperaciĆ³n: establecer el cĆ³digo postal de envĆ­o de modo que coincida con el cĆ³digo postal de facturaciĆ³n
Comparta sus comentarios de Trailhead en la Ayuda de Salesforce.

Nos encantarƭa saber mƔs sobre su experiencia con Trailhead. Ahora puede acceder al nuevo formulario de comentarios en cualquier momento en el sitio de Ayuda de Salesforce.

MĆ”s informaciĆ³n Continuar a Compartir comentarios