Contenido del curso
Gestión de modelos en el backend con el ORM Diesel
- 2

Qué es un ORM y por qué usar Diesel
02:55 min - 3

Errores Comunes al Instalar y Usar Diesel en Rust
00:31 min - 4

Instala Diesel ORM en tu proyecto Rust
05:16 min - 5

Modelo Post con Diesel y PostgreSQL
14:22 min - 6

Cómo insertar datos en Diesel con Rust
07:55 min - 7

Queries SELECT con filtros en Diesel
08:16 min - 8

Cómo editar registros con Diesel en Rust
04:40 min - 9

Borrar registros en Diesel con filtros
03:01 min
Actix web framework (controlador)
Tera templates (vistas)
Despliegue del proyecto
Continúa tu aprendizaje
Hola Mundo con Actix Web y PostgreSQL
Resumen
Configurar Actix Web en Rust te permite levantar un servidor HTTP en minutos y conectarlo a una base de datos PostgreSQL usando un pool de conexiones. Aquí aprendes a estructurar el main.rs, definir rutas con macros y entender por qué Rust exige la palabra move al pasar datos entre hilos. Es una guía pensada para quien ya conoce Diesel y quiere dar el salto a la capa web.
¿Qué dependencia necesito para usar Actix Web en Rust?
Todo empieza en el Cargo.toml. Ahí declaras la versión estable de Actix Web, que al momento de esta clase es la 4.0 [01:00].
toml [dependencies] actix-web = "4.0"
Dentro del archivo main.rs importas los elementos que vas a usar a lo largo del servidor: get, post, web, App, HttpResponse, HttpServer y Responder.
rust use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
El trait Responder es el que permite que una función devuelva una respuesta HTTP válida sin que tengas que construirla manualmente cada vez.
¿Cómo se estructura el main asíncrono de Actix?
Actix exige que tu aplicación sea asíncrona, así que la función main se marca con async y con el macro #[actix_web::main]. La salida es un std::io::Result<()> porque el servidor puede fallar al enlazar el puerto [01:45].
rust #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().service(hello_world) }) .bind(("0.0.0.0", 9900))? .run() .await }
Fíjate en tres detalles que suelen romper a quienes empiezan:
- La IP y el puerto van como tupla, no como argumentos separados.
binddevuelve unResult, así que necesitas?o.unwrap().- No pones punto y coma al final de
.awaitporque estás devolviendo el valor.
¿Qué hace el macro
#[actix_web::main]? Convierte tu funciónmainsíncrona en un runtime asíncrono compatible con Actix. Sin él, no puedes usarasync/awaitenmain.
¿Cómo creo una ruta y devuelvo Hola Platzi en el navegador?
La función que responde en la raíz es muy directa. Le pones el macro #[get("/")] para asociarla a una URL y devuelves un HttpResponse::Ok con el cuerpo que quieras [03:30].
rust #[get("/")] async fn hello_world() -> impl Responder { HttpResponse::Ok().body("Hola, Platzi") }
Un error típico aquí es dejar el punto y coma después de HttpResponse::Ok().body(...). Si lo haces, la función devuelve () en vez de un Responder y el compilador se queja. Esa es la azúcar sintáctica de Rust: la última expresión sin punto y coma es el valor de retorno.
Corre el proyecto con cargo run, abre el navegador en 0.0.0.0:9900 y vas a ver el mensaje en pantalla. Cualquier cambio en el código requiere detener el servidor con Ctrl + C y volver a ejecutar.
¿Cómo conecto Actix Web con PostgreSQL usando r2d2?
Una sola conexión a base de datos no escala. Por eso Diesel ofrece r2d2, una librería que crea un pool de conexiones reutilizables [05:30]. Necesitas dos imports clave:
rust use diesel::r2d2::Pool; use diesel::r2d2::{self, ConnectionManager};
En el Cargo.toml activa la feature r2d2 de Diesel para que el compilador encuentre estos módulos.
Dentro de main, después de cargar las variables del .env, construyes el manager y el pool:
rust let connection = ConnectionManager::<PgConnection>::new(db_url); let pool = Pool::builder() .build(connection) .expect("No se pudo construir la pool");
El expect te da un mensaje claro si la conexión falla al arrancar, lo cual ahorra horas de debugging.
¿Cómo paso el pool a las rutas con web::Data?
Actix usa web::Data para compartir estado entre handlers. Después de registrar el servicio, agregas el pool clonado al App:
rust HttpServer::new(move || { App::new() .service(hello_world) .app_data(web::Data::new(pool.clone())) })
Desde cualquier ruta, ahora puedes pedir el pool como parámetro y ejecutar queries de Diesel sin abrir conexiones nuevas a mano.
¿Qué es un pool de conexiones? Es un grupo de conexiones a la base de datos que se mantienen abiertas y se reparten entre las peticiones. Evita el costo de abrir y cerrar conexiones en cada request.
¿Por qué Actix obliga a escribir move antes del closure?
La palabra move aparece justo antes de las llaves del HttpServer::new y resuelve un tema profundo de Rust: el ownership [08:00]. Cuando el servidor arranca cada worker en un hilo distinto, necesita ser dueño de los datos que va a usar, en este caso el pool.
Sin move, el closure intentaría tomar prestado el pool del main, pero el main ya no existirá cuando los hilos estén corriendo. Con move, transfieres la propiedad del valor desde el hilo principal hacia cada hilo del servidor.
movetraslada la propiedad de las variables capturadas al closure.pool.clone()crea una referencia contable nueva para que cada worker tenga la suya.- Sin estos dos elementos, el código no compila.
Es uno de los superpoderes de Rust: te obliga a pensar en quién posee qué dato antes de ejecutar, y eso elimina toda una familia de errores de concurrencia en tiempo de compilación.
¿Ya levantaste tu servidor en el puerto 9900? Cuéntame en los comentarios qué mensaje pusiste en tu primer body y si el compilador te marcó algún typo en Connection o ConnectionManager.