Modelos

Estructura de modelos en la app

Creación

Los modelos se ubican en la carpeta: app/models. Para crear un nuevo modelo se debe usar el comando:

node ace make:model my_model

Para indicar cual es la tabla que usará el modelo, se debe especificar la variable estáctica: table

...
export default class Planificacion extends compose(...) {
    static table = 'planificacion.planificaciones'
}

Soft deleting

A fin de garantizar estabilidad de datos con el tiempo, se implementó la logica de un pseudo eliminado, donde los elementos que se marquen como eliminados tendrán un campo llamado: deleteAt. A su vez, cada modelo deberá heredar SoftDeletes del paquete: adonis-lucid-soft-deletes, ejemplo: app/models/planificacion/planificacion.ts

import { SoftDeletes } from 'adonis-lucid-soft-deletes'
export default class Planificacion extends compose(BaseModel, SoftDeletes) {
}
  • Obtener Archivados: Al trabajar con el softdeleting, se tendrá que tener una forma de acceder a los registros eliminados, para ello, este paquete implementa la función onlyTrashed que es agregada al modelo del cual se requieren traer sus elementos archivados, un ejemplo de ello lo podemos ver en: app/controllers/planificacion/planificacion_controller.ts
async index({ request, response, auth }: HttpContext) {
    ...
    let query = (data.trashed == 'true') ? Planificacion.onlyTrashed() : Planificacion.query();
    const planificaciones = await query.orderBy('created_at', 'asc').paginate(...);
    return response.status(200).send(planificaciones);
}
  • Restaurar: Si se necesita restaurar un elemento borrado, para ello requerimos aplicar el metodo restore() sobre el registro archivado, ejemplo: app/controllers/planificacion/planificacion_controller.ts
 async restore({ params, response }: HttpContext) {
    const id = params.id;
    const planificacion = await Planificacion.onlyTrashed().where('id', id).first()
    ...
    await planificacion.restore();
}
  • Eliminar definitivamente: Si por el contrario, necesitamos eliminar el registro por completo de la base de datos, debemos llamar a la función: forceDelete(), ejemplo: app/controllers/planificacion/planificacion_controller.ts
async destroy({ params, response }: HttpContext) {
    const id = params.id;
    const planificacion = await Planificacion.onlyTrashed().where('id', id).first()
    if (!planificacion) return response.status(404).send({ message: 'Planificacion no encontrada' });
    await planificacion.forceDelete()
}

Filtering

Para trabajar con consultas que necesitan implementar múltiples filtros a la vez, se ha instalado el paquete filters de adonijs, el cual permite aplicar filtros de forma estructurada a las consultas de una forma sencilla, para ello debemos heredar el objeto filterable en cada modelo que se desee aplicar filtering e indicar el archivo que se utilizará para el filtrado, ejemplo: app/models/planificacion/planificacion.ts

import { Filterable } from 'adonis-lucid-filter'
import PlanificacionFilter from '#models/filters/planificacion_filter'
export default class Planificacion extends compose(BaseModel, Filterable) {
    static $filter = () => PlanificacionFilter
}
  • Aplicación: Para aplicar los filters, se necesitará crear un archivo filter con el comando:
node ace make:filter my_model_filter

Esto creará un archivo con los filtros a aplicar al modelo necesario dentro la carpeta app/models/filters, ejemplo app/controllers/planificacion/planificacion_controller.ts

async index({ request, response, auth }: HttpContext) {
    ...
    const planificaciones = await Planificacion.query().filter(data)
        .orderBy('created_at', 'asc').paginate(...);
    ...
}

Donde el archivo app/models/filters/planificacion_filter.ts luce como:

import { BaseModelFilter } from 'adonis-lucid-filter'
import type { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model'
import Planificacion from '#models/planificacion/planificacion'

export default class PlanificacionFilter extends BaseModelFilter {
    declare $query: ModelQueryBuilderContract<typeof Planificacion>

    /* Filtrando por año */
    periodo(value: string): void {
        if (value != 'all') this.$query.where('periodo', value)
    }
    ...
    estado(value: string): void {
        if (value != 'all') this.$query.where('estado_id', value)
    }
}