Saltar al contenido

Complemento CreateRowOnEmptyTablePlugin

Resumen

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

Registro

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

Parámetros

Ninguno

Observaciones

CreateRowOnEmptyTablePlugin determina si el evento Filter devolvió alguna fila. Si el evento Filter devolvió una o más filas, el complemento sale sin 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 Nuevo. El evento Nuevo es responsable de aplicar criterios vinculantes, así como de invocar las reglas predeterminadas del objeto de datos. En el contexto de una solicitud de página web, los criterios vinculantes se derivan de los parámetros de la cadena de consultar 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 Nuevo, el complemento invoca el evento Insertar del objeto de datos y conserva la fila en la tabla de destino. Los desarrolladores pueden registrar acciones en el evento Insertar para realizar 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 Insertar 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 Insertar no tiene éxito porque fallaron una o más reglas de validación, el complemento se cierra sin más procesamiento. De lo contrario, el complemento verifica el alcance del cambio del evento Insertar para determinar si la fila debe actualizarse. Si el alcance del 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 activar una actualización si el objeto de datos contiene columnas calculadas o selecciones de varias tablas. Estos valores solo se resuelven mediante el evento Filtro.

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

Uso

Imagine que un desarrollador quiere crear un enlace que agregue automáticamente un producto al carrito de compras del usuario. El enlace podría verse así:

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

En este ejemplo, el enlace abre la página AddToCart y pasa ProductId como criterio vinculante.

Supongamos que la fuente de datos contiene una tabla Cart que se parece a esta:

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

El desarrollador comienza creando un objeto de datos AddToCart dirigido 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 ProductId como una columna vinculante. Al hacerlo, se garantiza que ProductId esté presente antes de ejecutar el evento. El objeto de datos AddToCart está restringido de modo que los usuarios solo puedan ver los artículos 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 que CartId esté predeterminado explícitamente, ya que se genera automáticamente. ProductId no está predeterminado porque se obtendrá a partir de criterios vinculantes.

Además del objeto de datos AddToCart, el desarrollador crea un objeto de datos denominado 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 de filtro explícito. No utiliza el complemento CreateRowOnEmptyTablePlugin.

Luego, el desarrollador crea una página denominada AddToCart y registra el objeto de datos AddToCart como el objeto de datos de la página. Luego, el desarrollador agrega un panel de varias filas a la página AddToCart. El panel de varias filas selecciona del 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 represente 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érico, vinculado a la columna Cantidad.

Ver la página sin proporcionar ningún criterio vinculante generará un error.

Nota

Al momento de escribir este artículo, las excepciones lanzadas al ejecutar el evento de filtro 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, Vinyl 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 Carrito. Después de que se ejecute el evento Filter del objeto de datos AddToCart, Vinyl 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 Carrito. Por ejemplo, el desarrollador podría registrar una regla CRAM que inserte una fila en la tabla Sesión 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 que pertenecen a sesiones caducadas.

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 ocurriría 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 

El Vinyl protege contra esta situación. Si el evento Filter no encuentra la nueva fila al realizar una actualización, se genera la siguiente excepción:

Se detectó bucle infinito 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 por segunda vez se obtiene el mismo resultado.

El complemento CreateRowOnEmptyTablePlugin es idempotente: actualizar la ventana del navegador no 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 insegura puede explotarse en un ataque de falsificación de solicitudes 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 reglas o complementos que interactúen con sistemas externos, como enviar un correo o realizar un pago.