Saltar al contenido

Complemento CreateRowOnEmptyTablePlugin

Resumen

Crea una nueva fila y la guarda en el objeto de datos si el evento de filtro no devuelve ninguna fila.

Registro

CreateRowOnEmptyTablePlugin es un complemento de acción para un evento a nivel de tabla. Debe registrarse para ejecutarse después del evento Filter. Debido a que el complemento altera el comportamiento del evento Filter intrínseco, debe registrarse en un objeto de datos, no en una tabla física.

Parámetros

Ninguno

Observaciones

El complemento CreateRowOnEmptyTablePlugin determina si el evento Filter devolvió alguna fila. Si el evento Filter devolvió una o más filas, el complemento finaliza sin realizar ningún procesamiento adicional. De lo contrario, el complemento crea una nueva fila y la conserva en el objeto de datos.

El complemento crea una fila invocando el evento New. El evento New es responsable de aplicar los criterios de vinculación, así como de invocar las reglas predeterminadas del objeto de datos. En el contexto de una solicitud de página web, los criterios de vinculación se derivan de los parámetros de la cadena de consultar de URL. En otras palabras, la nueva fila se completará con cualquier valor de parámetro de cadena de consultar cuyos nombres coincidan con los nombres de las columnas del objeto de datos.

Después de invocar el evento New, el complemento invoca el evento Insert del objeto de datos y conserva la fila en la tabla de destino. Los desarrolladores pueden registrar acciones en el evento Insert para realizar un procesamiento adicional. Esto es importante porque el evento Filter es un evento a nivel de tabla y, por lo tanto, no admite acciones a nivel de fila, como las reglas CRUD. Por el contrario, el evento Insert es un evento a nivel de fila. Los eventos a nivel de fila admiten la mayoría de las acciones, incluidas las reglas CRUD.

Si el evento Insert no se ejecuta correctamente debido a que una o más reglas de validación fallaron, el complemento sale sin realizar ningún procesamiento adicional. De lo contrario, el complemento verifica el alcance de cambio del evento Insert para determinar si se debe actualizar la fila. Si el alcance de cambio se establece en un valor distinto de "Ninguno", el complemento actualiza la fila. La operación de actualización invoca el evento Filter en la nueva fila.

Nota

Los desarrolladores deberían considerar configurar el alcance de cambio del evento Insertar para que active una actualización si el objeto de datos contiene columnas calculadas o selecciona de varias tablas. Estos valores solo se resuelven mediante el evento Filtro.

Finalmente, el complemento sale y devuelve la fila recién creada. Como todo esto sucede dentro del contexto del evento Filter, el cliente web no lo sabe. En lo que respecta al cliente web, la fila siempre existió.

Uso

Imaginemos que un desarrollador quiere crear un enlace que agregue automáticamente un producto al carrito de compras del usuario. El enlace podría ser similar a esto:

https://example.com/App Builder/app/Shop/AddToCart?ProductId=1234

En este ejemplo, el enlace abre la página AddToCart y pasa ProductId como criterio de vinculación.

Supongamos que la fuente de datos contiene una tabla de carrito que se parece a esto:

  • CartId - Identificador único, clave principal, generado automáticamente.
  • ProductId - Entero, clave externa a la tabla Producto.
  • Cantidad - Entero.
  • SessionId - Identificador único, identifica la sesión del usuario.

El desarrollador comienza creando un objeto de datos AddToCart que apunta a la tabla Cart. El objeto de datos AddToCart selecciona todas las columnas de la tabla Cart. Aunque técnicamente no es necesario, el desarrollador marca el ProductId como una columna de enlace. Al hacerlo, se asegura de que el ProductId esté presente antes de ejecutar el evento. El objeto de datos AddToCart está restringido de modo que los usuarios solo puedan ver los elementos del carrito que pertenecen a su sesión actual. La declaración mvSQL resultante podría verse así:

SELECT 
    C.CartId AS CartId,
    C.ProductId AS ProductId,
    C.Quantity AS Quantity,
    C.SessionId AS SessionId
FROM Cart AS C 
WHERE C.SessionId = session()

Tenga en cuenta que no es necesario establecer explícitamente el valor predeterminado de CartId, ya que se genera automáticamente. ProductId no tiene un valor predeterminado, ya que se obtendrá a partir de criterios vinculantes.

Además del objeto de datos AddToCart, el desarrollador crea un objeto de datos llamado MyCart. Al igual que el objeto de datos AddToCart, el objeto de datos MyCart apunta y selecciona todas las columnas de la tabla Cart. El objeto de datos MyCart también está restringido a la sesión actual. Sin embargo, el objeto de datos MyCart no tiene un evento Filter explícito. No utiliza el complemento CreateRowOnEmptyTablePlugin.

A continuación, el desarrollador crea una página denominada AddToCart y registra el objeto de datos AddToCart como objeto de datos de la página. A continuación, el desarrollador añade un panel de varias filas a la página AddToCart. El panel de varias filas selecciona desde el objeto de datos MyCart. Además, el panel de varias filas está vinculado al objeto de datos de la página.

Nota

Vincular un panel a la página garantiza que el panel no se muestre hasta que se ejecute el evento Filter del objeto de datos de la página.

El panel de varias filas contiene dos controles:

  • Producto: lista, vinculada a la columna ProductId. Selecciona de la tabla Producto utilizando ProductId como clave y ProductName como título.
  • Cantidad: numérica, vinculada a la columna Cantidad.

Ver la página sin proporcionar ningún criterio de vinculación generará un error.

Nota

Al momento de escribir este artículo, las excepciones lanzadas al ejecutar el evento Filter del objeto de página no se muestran en la pantalla. Sin embargo, aparecerán en el registro.

Si la cadena de consultar contiene un parámetro llamado ProductId con un valor válido, App Builder ejecutará el evento Filter del objeto de datos AddToCart, que a su vez ejecuta el complemento CreateRowOnEmptyTablePlugin. El complemento creará una nueva fila y la insertará en la tabla Cart. Después de que se ejecute el evento Filter del objeto de datos AddToCart, App Builder ejecutará el evento Filter del objeto de datos MyCart. Esto devolverá la fila recién creada y la mostrará en el panel de varias filas.

El desarrollador podría realizar acciones adicionales cuando se inserte la nueva fila en la tabla Cart. Por ejemplo, el desarrollador podría registrar una regla CRAM que inserte una fila en la tabla Session si no existe. La declaración mvSQL podría verse así:

INSERT INTO Session
(
    SessionId,
    DateCreated
)
SELECT
    SessionId,
    DateCreated
FROM
(
    SELECT
    session() AS SessionId,
    now() AS DateCreated
) AS SOURCE
WHERE NOT EXISTS
(
    SELECT 1
    FROM Session
    WHERE
        Session.SessionId = SOURCE.SessionId
        AND Session.DateCreated = SOURCE.DateCreated
)

Esto permitiría al desarrollador programar un evento que elimine los carritos pertenecientes a sesiones vencidas.

Errores

Bucles Infinitos

Debido a que CreateRowOnEmptyTablePlugin invoca el evento Filter de forma recursiva, existe la posibilidad de que se produzca un bucle infinito. Esto podría ocurrir si el desarrollador diseñara el objeto de datos de manera que no devolviera la fila recién creada. Por ejemplo:

SELECT *
FROM Table
WHERE 1 = 0 

App Builder protege contra esta situación. Si el evento de filtro no encuentra la nueva fila al realizar una actualización, se genera la siguiente excepción:

Bucle infinito detectado al crear una fila en una tabla vacía.

Seguridad

Cuando un navegador sigue un enlace, realiza una solicitud HTTP GET. Como regla general, una solicitud HTTP GET debe ser segura e idempotente. Una solicitud HTTP es segura si no tiene efectos secundarios. Una solicitud HTTP es idempotente si al realizar la misma solicitud una segunda vez se obtiene el mismo resultado.

El complemento CreateRowOnEmptyTablePlugin es idempotente: al actualizar la ventana del navegador no se creará una segunda fila. Sin embargo, el complemento CreateRowOnEmptyTablePlugin no es seguro: el complemento crea una fila persistente en la base de datos. Esto es, por definición, un efecto secundario.

Los desarrolladores deben tener esto en cuenta, ya que una solicitud GET no segura puede ser explotada en un ataque de falsificación de solicitud entre sitios. Por este motivo, los desarrolladores deben evitar cualquier operación potencialmente destructiva, como registrar una regla de eliminación que se ejecuta cuando se carga la página. Los desarrolladores también deben evitar registrar cualquier regla o complemento que interactúe con sistemas externos, como enviar un correo o realizar un pago.