diff --git a/src/place.rs b/src/place.rs index 88f517e..a505613 100644 --- a/src/place.rs +++ b/src/place.rs @@ -12,15 +12,3 @@ pub struct Place { pub longitude: f32, pub latitude: f32, } - -#[derive(Debug, Clone, Deserialize, Serialize)] -#[serde(crate = "rocket::serde")] -pub struct UpdatePlace { - pub name: Option, - pub address: Option, - pub open_hours: Option, - pub icon: Option, - pub description: Option, - pub longitude: Option, - pub latitude: Option, -} diff --git a/src/routes.rs b/src/routes.rs index d476aa2..95c8ea9 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,12 +1,12 @@ use rocket::fairing::{self, AdHoc}; -use rocket::response::status::Created; +use rocket::response::status::{Accepted, Created, NotFound}; use rocket::serde::json::Json; use rocket::{Build, Rocket}; use rocket_db_pools::{Connection, Database}; use rocket::futures::stream::TryStreamExt; -use crate::place::{Place, UpdatePlace}; +use crate::place::Place; type Result> = std::result::Result; #[derive(Database)] @@ -34,10 +34,50 @@ async fn get_places(mut db: Connection) -> Result>> { Ok(Json(places)) } +#[derive(Debug, Responder)] +enum UpsertResponse { + Created(Created>), + Accepted(Accepted>), + NotFound(NotFound>), +} + #[post("/places", format = "json", data = "")] -async fn create_place(mut db: Connection, place: Json) -> Result>> { - ::sqlx::query!( - "INSERT INTO places (name, address, open_hours, icon, description, longitude, latitude) VALUES (?, ?, ?, ?, ?, ?, ?)", +async fn upsert_place(db: Connection, place: Json) -> Result { + if place.id.is_some() { + update_place(db, place).await + } else { + insert_place(db, place).await + } +} + +struct Id { + id: i64, +} + +async fn insert_place(mut db: Connection, mut place: Json) -> Result { + let i = ::sqlx::query_as!( + Id, + "INSERT INTO places (name, address, open_hours, icon, description, longitude, latitude)\ + VALUES (?, ?, ?, ?, ?, ?, ?)\ + RETURNING id", + place.name, + place.address, + place.open_hours, + place.icon, + place.description, + place.longitude, + place.latitude + ) + .fetch_one(&mut *db) + .await?; + + place.id = Some(i.id); + Ok(UpsertResponse::Created(Created::new("/places").body(place))) +} + +async fn update_place(mut db: Connection, place: Json) -> Result { + let result = ::sqlx::query!( + "UPDATE places SET (name, address, open_hours, icon, description, longitude, latitude) = (?, ?, ?, ?, ?, ?, ?)", place.name, place.address, place.open_hours, @@ -49,12 +89,11 @@ async fn create_place(mut db: Connection, place: Json) -> Result", format = "json", data = "")] -fn update_place(id: i64, update_place: Json) -> &'static str { - "Hello, world!" + if result.rows_affected() == 1 { + Ok(UpsertResponse::Accepted(Accepted(Some(place)))) + } else { + Ok(UpsertResponse::NotFound(NotFound(place))) + } } #[delete("/places/")] @@ -84,9 +123,6 @@ pub fn stage() -> AdHoc { rocket .attach(Db::init()) .attach(AdHoc::try_on_ignite("SQLx Migrations", run_migrations)) - .mount( - "/", - routes![create_place, get_places, update_place, delete_place], - ) + .mount("/", routes![upsert_place, get_places, delete_place]) }) }