1
0
mirror of https://github.com/actix/actix-website synced 2024-11-27 18:12:57 +01:00

update database examples

This commit is contained in:
Rob Ede 2023-03-13 17:58:08 +00:00
parent 8ea575194e
commit 1a3fedc78f
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
3 changed files with 68 additions and 30 deletions

View File

@ -2,6 +2,7 @@
members = [ members = [
"application", "application",
"async-handlers", "async-handlers",
"databases",
"easy-form-handling", "easy-form-handling",
"either", "either",
"errors", "errors",
@ -23,5 +24,3 @@ members = [
"url-dispatch", "url-dispatch",
"websockets", "websockets",
] ]
# TODO: update databases
exclude = ["databases"]

View File

@ -5,3 +5,6 @@ edition = "2018"
[dependencies] [dependencies]
actix-web = "4" actix-web = "4"
diesel = { version = "2", features = ["sqlite", "r2d2"] }
serde = { version = "1", features = ["derive"] }
uuid = { version = "1", features = ["v4"] }

View File

@ -1,43 +1,76 @@
use std::io;
use actix_web::{error, web, App, HttpResponse, HttpServer, Responder};
use diesel::{prelude::*, r2d2, Insertable, Queryable, SqliteConnection};
use serde::Serialize;
mod schema {
diesel::table! {
users {
id -> VarChar,
name -> VarChar,
}
}
}
#[derive(Debug, Serialize, Queryable)]
struct User {
id: String,
name: String,
}
// <handler> // <handler>
fn insert_new_user(db: &SqliteConnection, user: CreateUser) -> Result<User, Error> { #[derive(Debug, Insertable)]
use self::schema::users::dsl::*; #[diesel(table_name = self::schema::users)]
struct NewUser<'a> {
id: &'a str,
name: &'a str,
}
fn insert_new_user(
conn: &mut SqliteConnection,
user_name: String,
) -> diesel::QueryResult<User> {
use crate::schema::users::dsl::*;
// Create insertion model // Create insertion model
let uuid = format!("{}", uuid::Uuid::new_v4()); let uid = format!("{}", uuid::Uuid::new_v4());
let new_user = models::NewUser { let new_user = NewUser {
id: &uuid, id: &uid,
name: &user.name, name: &user_name,
}; };
// normal diesel operations // normal diesel operations
diesel::insert_into(users) diesel::insert_into(users)
.values(&new_user) .values(&new_user)
.execute(&self.0) .execute(conn)
.expect("Error inserting person"); .expect("Error inserting person");
let mut items = users let user = users
.filter(id.eq(&uuid)) .filter(id.eq(&uid))
.load::<models::User>(&self.0) .first::<User>(conn)
.expect("Error loading person"); .expect("Error loading person that was just inserted");
Ok(items.pop().unwrap()) Ok(user)
} }
// </handler> // </handler>
// <main> // <main>
type DbPool = r2d2::Pool<ConnectionManager<SqliteConnection>>; type DbPool = r2d2::Pool<r2d2::ConnectionManager<SqliteConnection>>;
#[actix_web::main] #[actix_web::main]
async fn main() -> io::Result<()> { async fn main() -> io::Result<()> {
// Create connection pool // connect to SQLite DB
let manager = r2d2::ConnectionManager::<SqliteConnection>::new("app.db");
let pool = r2d2::Pool::builder() let pool = r2d2::Pool::builder()
.build(manager) .build(manager)
.expect("Failed to create pool."); .expect("database URL should be valid path to SQLite DB file");
// Start HTTP server // start HTTP server on port 8080
HttpServer::new(move || { HttpServer::new(move || {
App::new().app_data(web::Data::new(pool.clone())) App::new()
.resource("/{name}", web::get().to(index)) .app_data(web::Data::new(pool.clone()))
.route("/{name}", web::get().to(index))
}) })
.bind(("127.0.0.1", 8080))? .bind(("127.0.0.1", 8080))?
.run() .run()
@ -46,18 +79,21 @@ async fn main() -> io::Result<()> {
// </main> // </main>
// <index> // <index>
async fn index(pool: web::Data<DbPool>, name: web::Path<(String)>) -> impl Responder { async fn index(
let name = name.into_inner(); pool: web::Data<DbPool>,
name: web::Path<(String,)>,
) -> actix_web::Result<impl Responder> {
let (name,) = name.into_inner();
let user = web::block(move || { let user = web::block(move || {
let conn = pool.get().expect("couldn't get db connection from pool"); // Obtaining a connection from the pool is also a potentially blocking operation.
actions::insert_new_user(&conn, &user) // So, it should be called within the `web::block` closure, as well.
.await let mut conn = pool.get().expect("couldn't get db connection from pool");
.map_err(|e| {
eprintln!("{}", e); insert_new_user(&mut conn, name)
HttpResponse::InternalServerError().finish() })
} .await?
})?; .map_err(error::ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(user)) Ok(HttpResponse::Ok().json(user))
} }