-
-
Notifications
You must be signed in to change notification settings - Fork 0
Ejemplos
RAprogramm edited this page Jan 7, 2026
·
2 revisions
Ejemplos prácticos para casos de uso comunes.
Entidad de usuario clásica con campos de autenticación:
use entity_derive::Entity;
use uuid::Uuid;
use chrono::{DateTime, Utc};
#[derive(Entity)]
#[entity(table = "users", schema = "auth")]
pub struct User {
#[id]
pub id: Uuid,
#[field(create, update, response)]
pub username: String,
#[field(create, update, response)]
pub email: String,
#[field(create, update)] // Acepta pero nunca retorna
pub password_hash: String,
#[field(response)]
pub email_verified: bool,
#[field(update, response)]
pub avatar_url: Option<String>,
#[field(response)]
pub role: String,
#[field(skip)] // Campo de auditoría interno
pub last_login_ip: Option<String>,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
#[auto]
#[field(response)]
pub updated_at: DateTime<Utc>,
}Uso:
// Crear usuario
let request = CreateUserRequest {
username: "john_doe".into(),
email: "john@example.com".into(),
password_hash: hash_password("secret123"),
};
let user = pool.create(request).await?;
// Actualizar usuario
let update = UpdateUserRequest {
avatar_url: Some(Some("https://cdn.example.com/avatar.jpg".into())),
..Default::default()
};
let user = pool.update(user.id, update).await?;
// La respuesta es segura - sin password_hash, sin last_login_ip
let response = UserResponse::from(&user);Posts con relación de autor:
#[derive(Entity)]
#[entity(table = "posts", schema = "blog")]
pub struct Post {
#[id]
pub id: Uuid,
#[field(create, update, response)]
pub title: String,
#[field(create, update, response)]
pub slug: String,
#[field(create, update, response)]
pub content: String,
#[field(create, update, response)]
pub excerpt: Option<String>,
#[field(create, response)] // Se establece una vez, no se puede cambiar autor
pub author_id: Uuid,
#[field(update, response)]
pub published: bool,
#[field(update, response)]
pub published_at: Option<DateTime<Utc>>,
#[field(response)] // Solo lectura, gestionado por triggers
pub view_count: i64,
#[field(skip)] // Moderación interna
pub moderation_status: String,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
#[auto]
#[field(response)]
pub updated_at: DateTime<Utc>,
}Categorías con muchos-a-muchos:
#[derive(Entity)]
#[entity(table = "categories", schema = "blog")]
pub struct Category {
#[id]
pub id: Uuid,
#[field(create, update, response)]
pub name: String,
#[field(create, update, response)]
pub slug: String,
#[field(create, update, response)]
pub description: Option<String>,
#[field(response)]
pub post_count: i64, // Campo calculado
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
}Catálogo de productos:
#[derive(Entity)]
#[entity(table = "products", schema = "catalog")]
pub struct Product {
#[id]
pub id: Uuid,
#[field(create, update, response)]
pub name: String,
#[field(create, update, response)]
pub sku: String,
#[field(create, update, response)]
pub description: Option<String>,
#[field(create, update, response)]
pub price_cents: i64,
#[field(create, update, response)]
pub currency: String,
#[field(update, response)]
pub stock_quantity: i32,
#[field(update, response)]
pub is_active: bool,
#[field(create, response)]
pub category_id: Uuid,
#[field(skip)] // Seguimiento interno de costos
pub cost_cents: i64,
#[field(skip)] // Info del proveedor
pub supplier_id: Option<Uuid>,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
#[auto]
#[field(response)]
pub updated_at: DateTime<Utc>,
}Pedidos con seguimiento de estado:
#[derive(Entity)]
#[entity(table = "orders", schema = "sales")]
pub struct Order {
#[id]
pub id: Uuid,
#[field(create, response)]
pub customer_id: Uuid,
#[field(response)]
pub order_number: String, // Generado por secuencia de BD
#[field(update, response)]
pub status: String,
#[field(create, response)]
pub total_cents: i64,
#[field(create, response)]
pub currency: String,
#[field(create, update, response)]
pub shipping_address: String,
#[field(update, response)]
pub tracking_number: Option<String>,
#[field(skip)] // Datos del procesador de pago
pub payment_intent_id: Option<String>,
#[field(skip)] // Notas internas
pub admin_notes: Option<String>,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
#[auto]
#[field(response)]
pub updated_at: DateTime<Utc>,
}Entidades con ámbito de organización:
#[derive(Entity)]
#[entity(table = "organizations", schema = "tenants")]
pub struct Organization {
#[id]
pub id: Uuid,
#[field(create, update, response)]
pub name: String,
#[field(create, response)]
pub slug: String, // Inmutable después de creación
#[field(update, response)]
pub plan: String,
#[field(response)]
pub member_count: i32,
#[field(skip)] // Info de facturación
pub stripe_customer_id: Option<String>,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
}
#[derive(Entity)]
#[entity(table = "projects", schema = "tenants")]
pub struct Project {
#[id]
pub id: Uuid,
#[field(create, response)] // Se establece una vez
pub organization_id: Uuid,
#[field(create, update, response)]
pub name: String,
#[field(create, update, response)]
pub description: Option<String>,
#[field(update, response)]
pub archived: bool,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
#[auto]
#[field(response)]
pub updated_at: DateTime<Utc>,
}Para contratos de API sin persistencia:
#[derive(Entity)]
#[entity(table = "webhooks", sql = "none")]
pub struct WebhookPayload {
#[id]
pub id: Uuid,
#[field(create, response)]
pub event_type: String,
#[field(create, response)]
pub payload: String,
#[field(create, response)]
pub timestamp: DateTime<Utc>,
#[field(response)]
pub signature: String,
}Esto genera solo:
CreateWebhookPayloadRequestWebhookPayloadResponse- Implementaciones
From
Sin repositorio, sin SQL, sin estructuras Row/Insertable.
Cuando el CRUD estándar no es suficiente:
#[derive(Entity)]
#[entity(table = "analytics_events", schema = "analytics", sql = "trait")]
pub struct AnalyticsEvent {
#[id]
pub id: Uuid,
#[field(create, response)]
pub event_name: String,
#[field(create, response)]
pub user_id: Option<Uuid>,
#[field(create, response)]
pub properties: serde_json::Value,
#[auto]
#[field(response)]
pub created_at: DateTime<Utc>,
}
// Implementa consultas personalizadas tú mismo:
impl AnalyticsEventRepository for PgPool {
type Error = sqlx::Error;
async fn create(&self, dto: CreateAnalyticsEventRequest) -> Result<AnalyticsEvent, Self::Error> {
// Inserción por lotes, tablas particionadas, etc.
}
async fn find_by_id(&self, id: Uuid) -> Result<Option<AnalyticsEvent>, Self::Error> {
// Consulta con particionamiento basado en tiempo
}
// Métodos personalizados más allá del CRUD:
async fn aggregate_by_event(&self, start: DateTime<Utc>, end: DateTime<Utc>)
-> Result<Vec<EventAggregate>, Self::Error> {
// Consulta de agregación compleja
}
}- Atributos — Referencia completa de atributos
- SQL Personalizado — Implementación de repositorio personalizado
- Frameworks Web — Integración con Axum/Actix
🇬🇧 English | 🇷🇺 Русский | 🇰🇷 한국어 | 🇪🇸 Español | 🇨🇳 中文
🇬🇧 English | 🇷🇺 Русский | 🇰🇷 한국어 | 🇪🇸 Español | 🇨🇳 中文
Getting Started
Features
Advanced
Начало работы
Возможности
Продвинутое
시작하기
기능
고급
Comenzando
Características
Avanzado
入门
功能
高级