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:
parent
8ea575194e
commit
1a3fedc78f
@ -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"]
|
|
||||||
|
@ -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"] }
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user