Secuencia de comandos en el lado del servidor

Las secuencias de comandos se ejecutan en JavaScript como una secuencia de comandos de Google Apps Script. Estas tienen acceso a las API de Apps Script, como también a las API y objetos en el lado del servidor de App Maker. Ten en cuenta que los servicios avanzados de Google deben estar habilitados antes de poder usarlos.

Conceptos básicos de secuencias de comandos en el lado del servidor

Tienes que usar secuencias de comandos en el lado del servidor cuando necesitas realizar cálculos que llevan tiempo (para evitar el bloqueo de la IU) o cuando necesitas acceder a la información que preferirías no enviar al cliente por su gran tamaño o por cuestiones de seguridad.

Llama a una secuencia de comandos del servidor

Para llamar a una secuencia de comandos del servidor, usa google.script.run. Consulta la documentación sobre la secuencia de comandos en el lado del servidor para obtener más información.

Parámetros y valores de muestra

Los valores se muestran en el método withSuccessHandler(function) en google.script.run. Los parámetros legales y valores de muestra son primitivos de JavaScript, como Number, Boolean y String, como también objetos y arreglos de JavaScript compuestos por primitivos, objetos y arreglos.

Una solicitud fallaría si intentaras pasar un objeto Date, una Function, un Record o un widget de App Maker, por ejemplo. Una estrategia común para pasar objetos más complejos es usar JSON.stringify y JSON.parse.

Oculta secuencias de comandos del servidor

Es importante tener en cuenta que cualquier función que defines en una secuencia de comandos del servidor está abierta para todos los usuarios de tu aplicación, incluso si no la expones en la IU. Si quieres escribir una función de utilidad que pueda solo llamarse desde otras secuencias de comandos del servidor, debes adjuntar un guion bajo al nombre. Por ejemplo, el método siguiente sería público y permitiría que cualquier cliente obtenga el salario del usuario aprobado.

function calculateUserSalary(user) {
  // Gets the salary of the user...
  return salary;
}

En cambio, se debería ver de la manera siguiente:

function calculateUserSalary_(user) {
  // Gets the salary of the user...
  return salary;
}

Seguridad

Si bien es útil ocultar las secuencias de comandos del servidor, a veces, es posible que las secuencias de comandos de tu servidor tengan que exponer datos sensibles al cliente. En este caso, es importante asegurar tus secuencias de comandos. Si bien los modelos y las vistas tienen permisos, para las secuencias de comandos del servidor tienes que implementar los tuyos. Si usas el ejemplo de arriba, supongamos que quieres que tus usuarios puedan llamarla, pero solo quieres que se muestre el salario de un usuario si el usuario mismo o un administrador lo solicitan.

function calculateUserSalary(user) {
  var currentUser = Session.getActiveUser().getEmail();
  if (currentUser !== user && !isManager(currentUser, user) {
    throw new Error(currentUser +
        " does not have access to salary for " + user);
  }

  // Gets the salary of the user...
  return salary;
}

Trabaja con datos

Las secuencias de comandos del servidor te permiten interactuar con los todos modelos de App Maker de forma genérica. Te permiten crear registros nuevos, consultar o editar relaciones.

Crea registros

// Assume a model called "Fruits" with a string field called "Name".
var newRecord = app.models.Fruits.newRecord();
newRecord.Name = "Kiwi";  // properties/fields can be read and written.
app.saveRecords([newRecord]);  // The changes won't be committed to the
                               // database unless you remember to save.

Consulta registros

var query = app.models.Person.newQuery();
query.filters.Name._equals = "John";

var records = query.run();
console.log("Found " + records.length + " Johns.");

for (var i in records) {
    var person = records[i];
    console.log("Found person named John " + person.FamilyName);
}

Trabaja con las relaciones

En el ejemplo siguiente, se muestra cómo crear y consultar registros relacionados. Supongamos que tenemos un modelo “Address”, con una relación de varios a uno con un modelo “Country”.

var address1 = app.models.Address.newRecord();
address1.zip = 94040;
var address2 = app.models.Address.newRecord();
address2.zip = 94041;
app.saveRecords([address1, address2]); // Save created records.

var query = app.models.Country.newQuery();
query.filters.Name._equals = countryName;
var country = query.run()[0];

country.Address.push(address1, address2);
app.saveRecords([country]); // Save updated relation.

También puedes filtrar por campos relacionados, como en el fragmento de código a continuación:

function addressesForCountry(countryName) {
  var query = app.models.Address.newQuery();
  query.filters.Country.Name._equals = countryName;

  var records = query.run();
  return records;
};

Puedes encontrar más información en la sección Filtra relaciones.

Controla las transacciones de Cloud SQL

En el ejemplo a continuación, se muestra cómo usar una secuencia de comandos del servidor para controlar las transacciones de Cloud SQL. Usa esta API para realizar las acciones siguientes:

  • comenzar una transacción y bloquear registros relacionados
  • confirmar los cambios nuevos a la base de datos
  • revertir una transacción
function submitOrder(orderKey) {

  // Sets a rollback point and starts a new transaction.
  app.transaction.cloudSql.start();

   // Locks all records that are read in the transaction until the end of the transaction.
  app.transaction.cloudSql.setLockOnRead(app.transaction.cloudSql.lockOnRead.UPDATE);

  var orderQuery = app.models.Order.newQuery();
  orderQuery.filters._key._equals = orderKey;
  var order = orderQuery.run()[0];

  // Read related order items
  var orderItems = order.OrderItems;

  var products = [];
  for (var i = 0; i < orderItems.length; i++) {
    // Read related product
    var product  = orderItem.Product;

    if (product.InStockQuantity < orderItem.Quantity) {
      // Insufficient stock to complete an order; transaction is rolled back.
      app.transaction.cloudSql.rollback();
      throw new app.ManagedError("Not enough " + product.Name + " in stock. " +
                                 product.InStockQuantity + " Order: " +
                                 orderItem.Quantity + " can't be completed.");
    }

    // Reduce inStock quantity
    product.InStockQuantity = product.InStockQuantity - orderItem.Quantity;
    products.push(product);
  }

  order.Status = "Submitted";
  app.saveRecords(products);
  app.saveRecords([order]);

  // Order is successfully processed; database changes committed.
  app.transaction.cloudSql.commit();

  return "Order submitted: " + orderKey;
}

Solución de problemas

App Maker expone los errores de sintaxis mientras escribes y los resalta en color rojo. También detecta problemas comunes (como variables sin usar) y los informa como advertencias.

A veces, tus secuencias de comandos no funcionan como se espera, en este caso, App Maker proporciona un objeto console que se puede usar para registrar toda información relevante. Por ejemplo:

function getRecordsForCurrentUser() {
  var currentUser = Session.getActiveUser().getEmail();
  var query = app.models.Person.newQuery();
  query.filters.Email._equals = currentUser;

  var records = query.run();
  console.log("Found " + records.length + " records for " + currentUser);
  return records;
};

Los registros se pueden ver por separado para cada implementación de la aplicación.