Skip to content

Atributos

RAprogramm edited this page Jan 7, 2026 · 2 revisions

Guía completa de todos los atributos soportados por entity-derive.

Atributos a Nivel de Entidad

Se aplican a la estructura con #[entity(...)]:

#[derive(Entity)]
#[entity(
    table = "users",
    schema = "core",
    sql = "full",
    dialect = "postgres",
    uuid = "v7",
    soft_delete,
    returning = "full",
    error = "AppError",
    events,
    hooks,
    commands
)]
pub struct User { /* ... */ }

Referencia Rápida

Atributo Requerido Por Defecto Descripción
table Nombre de la tabla en BD
schema No "public" Esquema de BD
sql No "full" Nivel de generación SQL
dialect No "postgres" Dialecto de BD
uuid No "v7" Versión UUID para generación de ID
soft_delete No false Habilitar borrado lógico
returning No "full" Modo de cláusula RETURNING
error No sqlx::Error Tipo de error personalizado
events No false Generar eventos de ciclo de vida
hooks No false Generar trait de hooks
commands No false Habilitar patrón CQRS

table (requerido)

Nombre de la tabla en base de datos.

#[entity(table = "users")]           // → FROM users
#[entity(table = "user_profiles")]   // → FROM user_profiles

schema (opcional)

Esquema de base de datos. Por defecto: "public".

#[entity(table = "users")]                    // → FROM public.users
#[entity(table = "users", schema = "core")]   // → FROM core.users
#[entity(table = "users", schema = "auth")]   // → FROM auth.users

sql (opcional)

Nivel de generación SQL. Por defecto: "full".

Valor Trait Repository Impl PgPool Caso de Uso
"full" Entidades CRUD estándar
"trait" No Consultas personalizadas (joins, CTEs)
"none" No No Solo DTOs, sin base de datos
#[entity(table = "users", sql = "full")]   // Automatización completa (defecto)
#[entity(table = "users", sql = "trait")]  // Solo trait, implementar SQL manualmente
#[entity(table = "users", sql = "none")]   // Sin capa de base de datos

dialect (opcional)

Dialecto de BD para generación SQL. Por defecto: "postgres".

Dialecto Alias Tipo Cliente Estado
"postgres" "pg", "postgresql" sqlx::PgPool Estable
"clickhouse" "ch" clickhouse::Client Planificado
"mongodb" "mongo" mongodb::Client Planificado

uuid (opcional)

Versión UUID para claves primarias auto-generadas. Por defecto: "v7".

Versión Método Propiedades
"v7" Uuid::now_v7() Ordenado por tiempo, ordenable (recomendado)
"v4" Uuid::new_v4() Aleatorio, ampliamente compatible
#[entity(table = "users", uuid = "v7")]     // Ordenado por tiempo (defecto)
#[entity(table = "sessions", uuid = "v4")]  // UUID aleatorio

¿Por qué UUID v7?

  • Ordenado por tiempo: ordenamiento natural por fecha de creación
  • Mejor rendimiento de índices en BD
  • No requiere coordinación (a diferencia de secuencias)
  • Globalmente único en sistemas distribuidos

soft_delete (opcional)

Habilita borrado lógico para marcar registros como eliminados en lugar de borrarlos.

#[derive(Entity)]
#[entity(table = "documents", soft_delete)]
pub struct Document {
    #[id]
    pub id: Uuid,

    #[field(create, response)]
    pub title: String,

    #[field(skip)]
    pub deleted_at: Option<DateTime<Utc>>,  // Campo requerido
}

Métodos generados:

  • delete() — Establece deleted_at = NOW() en lugar de DELETE
  • hard_delete() — Elimina permanentemente el registro
  • restore() — Establece deleted_at = NULL
  • find_by_id() / list() — Filtran automáticamente registros eliminados
  • find_by_id_with_deleted() / list_with_deleted() — Incluyen registros eliminados

returning (opcional)

Controla qué datos se obtienen después de INSERT/UPDATE. Por defecto: "full".

Modo Cláusula SQL Caso de Uso
"full" RETURNING * Obtener todos los campos incluyendo los generados por BD
"id" RETURNING id Confirmar inserción, devolver entidad pre-construida
"none" (sin RETURNING) Fire-and-forget, opción más rápida
"col1, col2" RETURNING col1, col2 Devolver columnas específicas
#[entity(table = "logs", returning = "none")]              // Más rápido
#[entity(table = "users", returning = "full")]             // Obtener valores generados
#[entity(table = "events", returning = "id, created_at")]  // Columnas personalizadas

error (opcional)

Tipo de error personalizado para repositorio. Por defecto: sqlx::Error.

#[derive(Debug)]
pub enum AppError {
    Database(sqlx::Error),
    NotFound,
    Validation(String),
}

impl std::error::Error for AppError {}
impl std::fmt::Display for AppError { /* ... */ }

// Requerido: convertir desde sqlx::Error
impl From<sqlx::Error> for AppError {
    fn from(err: sqlx::Error) -> Self {
        AppError::Database(err)
    }
}

#[derive(Entity)]
#[entity(table = "users", error = "AppError")]
pub struct User { /* ... */ }

// El repositorio generado usa AppError:
// impl UserRepository for PgPool {
//     type Error = AppError;
//     ...
// }

events (opcional)

Genera enum de eventos del ciclo de vida. Ver Eventos para detalles.

#[entity(table = "orders", events)]

Generado:

pub enum OrderEvent {
    Created(Order),
    Updated { id: Uuid, changes: UpdateOrderRequest },
    Deleted(Uuid),
}

hooks (opcional)

Genera trait de hooks del ciclo de vida. Ver Ganchos para detalles.

#[entity(table = "users", hooks)]

Generado:

#[async_trait]
pub trait UserHooks: Send + Sync {
    type Error: std::error::Error + Send + Sync;

    async fn before_create(&self, dto: &mut CreateUserRequest) -> Result<(), Self::Error>;
    async fn after_create(&self, entity: &User) -> Result<(), Self::Error>;
    async fn before_update(&self, id: &Uuid, dto: &mut UpdateUserRequest) -> Result<(), Self::Error>;
    async fn after_update(&self, entity: &User) -> Result<(), Self::Error>;
    async fn before_delete(&self, id: &Uuid) -> Result<(), Self::Error>;
    async fn after_delete(&self, id: &Uuid) -> Result<(), Self::Error>;
}

commands (opcional)

Habilita patrón de comandos CQRS. Ver Comandos para detalles.

#[entity(table = "users", commands)]
#[command(Register)]
#[command(Deactivate, requires_id)]

Atributos a Nivel de Campo

Se aplican a campos individuales.

#[id]

Marca el campo de clave primaria.

Comportamiento:

  • Auto-genera UUID (v7 por defecto, configurable con atributo uuid)
  • Siempre incluido en DTO Response
  • Excluido de CreateRequest y UpdateRequest
#[id]
pub id: Uuid,

#[auto]

Marca campos auto-generados (timestamps, secuencias).

Comportamiento:

  • Obtiene Default::default() en From<CreateRequest>
  • Excluido de CreateRequest y UpdateRequest
  • Puede incluirse en Response con #[field(response)]
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,

#[field(...)]

Controla inclusión en DTOs. Combina múltiples opciones:

#[field(create)]                    // Solo en CreateRequest
#[field(update)]                    // Solo en UpdateRequest
#[field(response)]                  // Solo en Response
#[field(create, response)]          // En Create y Response
#[field(create, update, response)]  // En los tres
#[field(skip)]                      // Excluido de todos los DTOs

create

Incluye campo en DTO CreateRequest.

#[field(create)]
pub email: String,

// Generado:
pub struct CreateUserRequest {
    pub email: String,
}

update

Incluye campo en DTO UpdateRequest.

Importante: Los campos no opcionales se envuelven automáticamente en Option<T> para actualizaciones parciales.

#[field(update)]
pub name: String,  // No Option

// Generado:
pub struct UpdateUserRequest {
    pub name: Option<String>,  // Envuelto automáticamente
}

response

Incluye campo en DTO Response.

#[field(response)]
pub email: String,

// Generado:
pub struct UserResponse {
    pub id: Uuid,        // Siempre incluido (tiene #[id])
    pub email: String,   // Incluido
}

skip

Excluye campo de todos los DTOs. Usar para datos sensibles.

#[field(skip)]
pub password_hash: String,

Importante: skip anula todas las demás opciones de campo. El campo solo existirá en:

  • Estructura de entidad original
  • Estructura Row (para lecturas de BD)
  • Estructura Insertable (para escrituras en BD)

#[filter] / #[filter(...)]

Genera campos de filtro de consulta. Ver Filtrado para detalles.

#[filter]              // Coincidencia exacta: WHERE field = $n
#[filter(eq)]          // Igual que arriba
#[filter(like)]        // Patrón: WHERE field ILIKE $n
#[filter(range)]       // Rango: WHERE field >= $n AND field <= $m

#[belongs_to(Entity)]

Relación de clave foránea. Ver Relaciones para detalles.

#[belongs_to(User)]
pub user_id: Uuid,

Generado: Método find_user() en repositorio.

#[has_many(Entity)]

Relación uno-a-muchos (nivel de entidad). Ver Relaciones para detalles.

#[has_many(Post)]
pub struct User { /* ... */ }

Generado: Método find_posts() en repositorio.

#[projection(Name: fields)]

Genera estructura de vista parcial (nivel de entidad).

#[projection(Public: id, name, avatar)]
#[projection(Admin: id, name, email, role)]
pub struct User { /* ... */ }

Generado:

  • UserPublic { id, name, avatar }
  • UserAdmin { id, name, email, role }
  • Implementaciones From<User>
  • Métodos find_by_id_public(), find_by_id_admin()

Atributos de Comando

Se aplican a nivel de entidad con #[command(...)].

Referencia Rápida

Sintaxis Efecto
#[command(Name)] Usa todos los campos #[field(create)]
#[command(Name: field1, field2)] Usa solo campos especificados (añade requires_id)
#[command(Name, requires_id)] Añade campo ID, sin otros campos
#[command(Name, source = "create")] Usa explícitamente campos create (defecto)
#[command(Name, source = "update")] Usa campos update (opcionales, añade requires_id)
#[command(Name, source = "none")] Sin campos de payload
#[command(Name, payload = "Type")] Usa estructura payload personalizada
#[command(Name, result = "Type")] Usa tipo de resultado personalizado
#[command(Name, kind = "create")] Sugerencia: crea entidad (defecto)
#[command(Name, kind = "update")] Sugerencia: modifica entidad
#[command(Name, kind = "delete")] Sugerencia: elimina entidad (devuelve ())
#[command(Name, kind = "custom")] Sugerencia: operación personalizada

Ver Comandos para documentación detallada.

Ejemplo Completo

#[derive(Entity)]
#[entity(
    table = "posts",
    schema = "blog",
    sql = "full",
    dialect = "postgres",
    uuid = "v7",
    soft_delete,
    returning = "full",
    events,
    hooks,
    commands
)]
#[has_many(Comment)]
#[projection(Summary: id, title, author_id, created_at)]
#[command(Publish)]
#[command(Archive, requires_id)]
pub struct Post {
    #[id]
    pub id: Uuid,

    #[field(create, update, response)]
    #[filter(like)]
    pub title: String,

    #[field(create, update, response)]
    pub content: String,

    #[field(create, response)]
    #[belongs_to(User)]
    #[filter]
    pub author_id: Uuid,

    #[field(update, response)]
    pub published: bool,

    #[field(response)]
    #[filter(range)]
    pub view_count: i64,

    #[field(skip)]
    pub moderation_notes: String,

    #[field(skip)]
    pub deleted_at: Option<DateTime<Utc>>,

    #[auto]
    #[field(response)]
    #[filter(range)]
    pub created_at: DateTime<Utc>,

    #[auto]
    #[field(response)]
    pub updated_at: DateTime<Utc>,
}

Matriz de Decisiones

Quiero... Atributos
Auto-generar clave primaria #[id]
Usar UUID aleatorio uuid = "v4" en entidad
Usar UUID ordenado por tiempo uuid = "v7" (defecto)
Aceptar en cuerpo POST #[field(create)]
Aceptar en cuerpo PATCH #[field(update)]
Devolver en respuesta API #[field(response)]
Aceptar y devolver #[field(create, update, response)]
Ocultar de todas las APIs #[field(skip)]
Auto-generar timestamp #[auto] + #[field(response)]
Solo lectura (gestionado por BD) Solo #[field(response)]
Solo escritura (sin retorno) Solo #[field(create)]
Consultas SQL personalizadas sql = "trait"
Solo DTOs, sin BD sql = "none"
Borrado lógico de registros soft_delete en entidad
Tipo de error personalizado error = "MyError" en entidad
Filtrar por valor exacto #[filter] en campo
Filtrar por patrón #[filter(like)] en campo
Filtrar por rango #[filter(range)] en campo
Rastrear cambios de entidad events en entidad
Ejecutar código en ciclo de vida hooks en entidad
Usar comandos de dominio commands en entidad + #[command(...)]
Definir relación #[belongs_to(Entity)] o #[has_many(Entity)]
Vista parcial de entidad #[projection(Name: fields)]

Clone this wiki locally