From a7c734d39512385177426bcb2131726906ce2fff Mon Sep 17 00:00:00 2001 From: Harald Eilertsen Date: Mon, 8 Apr 2019 12:31:26 +0200 Subject: Add endpoint to fetch screenings from the database. Not entirely happy about the way this turned out for now. A more ergonomic return type from the models::screenings::get_all() function will be investigated. --- Cargo.lock | 29 +++++++++++++++++ Cargo.toml | 3 +- src/controllers.rs | 1 + src/controllers/screening.rs | 32 ++++++++++++++++++ src/lib.rs | 5 +-- src/models.rs | 1 + src/models/screening.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++ tests/apitests.rs | 34 +++++++++++++++++-- 8 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 src/controllers/screening.rs create mode 100644 src/models/screening.rs diff --git a/Cargo.lock b/Cargo.lock index 046159b..a2f3343 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,17 @@ name = "cfg-if" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chrono" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cookie" version = "0.11.0" @@ -127,6 +138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_derives 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pq-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "r2d2 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -426,6 +438,19 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" version = "1.10.0" @@ -497,6 +522,7 @@ dependencies = [ name = "ramaskrik" version = "0.1.0" dependencies = [ + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -889,6 +915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf" "checksum devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3" "checksum devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7" @@ -927,6 +954,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9cc7ed2bd4b7edad3ee93b659c38e53dabb619f7274e127a0fab054ad2bb998d" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c26d2b92e47063ffce70d3e3b1bd097af121a9e0db07ca38a6cc1cf0cc85ff25" "checksum pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e" diff --git a/Cargo.toml b/Cargo.toml index 973cedb..c9a36a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ authors = ["haraldei"] edition = "2018" [dependencies] -diesel = { version = "1.4.1", features = ["postgres"] } +chrono = { version = "0.4", features = ["serde"] } +diesel = { version = "1.4.1", features = ["chrono", "postgres"] } dotenv = "0.13.0" rocket = "0.4.0" serde = "1.0.89" diff --git a/src/controllers.rs b/src/controllers.rs index f5b1f08..40d910c 100644 --- a/src/controllers.rs +++ b/src/controllers.rs @@ -18,3 +18,4 @@ pub mod film; pub mod room; +pub mod screening; diff --git a/src/controllers/screening.rs b/src/controllers/screening.rs new file mode 100644 index 0000000..d060eb7 --- /dev/null +++ b/src/controllers/screening.rs @@ -0,0 +1,32 @@ +/* + Social program for Ramaskrik. + Copyright (C) 2019 Harald Eilertsen + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +use crate::{ + db, + models::{screening::{self, Screening}, film::Film, room::Room}, +}; + +use rocket::get; +use rocket_contrib::{ + json::Json, +}; + +#[get("/")] +pub fn get_screenings(db: db::Connection) -> Json, Option)>> { + Json(screening::get_all(&db).unwrap()) +} diff --git a/src/lib.rs b/src/lib.rs index a0eabc8..6554e7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ mod controllers; pub mod db; pub mod models; pub mod schema; -use crate::controllers::{film, room}; +use crate::controllers::{film, room, screening}; use rocket::routes; use std::collections::HashMap; @@ -44,5 +44,6 @@ pub fn build_rocket(db_url: &str) -> Result> { .attach(db::Connection::fairing()) .mount("/", rocket_contrib::serve::StaticFiles::from("./public")) .mount("/rooms", routes![room::get_rooms]) - .mount("/films", routes![film::get_films])) + .mount("/films", routes![film::get_films]) + .mount("/screenings", routes![screening::get_screenings])) } diff --git a/src/models.rs b/src/models.rs index f5b1f08..40d910c 100644 --- a/src/models.rs +++ b/src/models.rs @@ -18,3 +18,4 @@ pub mod film; pub mod room; +pub mod screening; diff --git a/src/models/screening.rs b/src/models/screening.rs new file mode 100644 index 0000000..cd08e88 --- /dev/null +++ b/src/models/screening.rs @@ -0,0 +1,77 @@ +/* + Social program for Ramaskrik. + Copyright (C) 2019 Harald Eilertsen + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +use crate::{ + db::Connection, + models::{film::Film, room::Room}, + schema::*, +}; +use diesel::prelude::*; +use serde_derive::{Deserialize, Serialize}; + +joinable!(screenings -> rooms (room_id)); +joinable!(screenings -> films (film_id)); + +#[derive(Deserialize, Identifiable, PartialEq, Serialize, Queryable)] +pub struct Screening { + pub id: i32, + pub film_id: i32, + pub room_id: i32, + pub date: chrono::NaiveDate, + pub start_time: chrono::NaiveTime, + pub end_time: chrono::NaiveTime, +} + +#[derive(Deserialize, Insertable)] +#[table_name = "screenings"] +pub struct NewScreening { + pub film_id: i32, + pub room_id: i32, + pub date: chrono::NaiveDate, + pub start_time: chrono::NaiveTime, + pub end_time: chrono::NaiveTime, +} + +pub fn get_all(db: &Connection) -> QueryResult, Option)>> { + use crate::schema::screenings::dsl::*; + screenings + .left_join(films::table) + .left_join(rooms::table) + .get_results::<(Screening, Option, Option)>(&**db) +} + +pub fn create( + room: &Room, + film: &Film, + date: chrono::NaiveDate, + start_time: chrono::NaiveTime, + end_time: chrono::NaiveTime, + db: &Connection) -> QueryResult +{ + let s = NewScreening { + room_id: room.id, + film_id: film.id, + date: date, + start_time: start_time, + end_time: end_time, + }; + + diesel::insert_into(screenings::table) + .values(&s) + .execute(&**db) +} diff --git a/tests/apitests.rs b/tests/apitests.rs index efcbfd2..4a74810 100644 --- a/tests/apitests.rs +++ b/tests/apitests.rs @@ -18,8 +18,10 @@ use ramaskrik; use ramaskrik::models::{ + self, film::{ Film, NewFilm }, - room::Room + room::Room, + screening, }; use lazy_static::lazy_static; @@ -77,7 +79,7 @@ fn load_default_rooms(db: &ramaskrik::db::Connection) { } fn load_fixtures(db: &ramaskrik::db::Connection) { - diesel::dsl::sql_query("TRUNCATE TABLE rooms, films").execute(&**db).unwrap(); + diesel::dsl::sql_query("TRUNCATE TABLE rooms, screenings, films").execute(&**db).unwrap(); load_default_rooms(&db); load_default_films(&db); } @@ -119,3 +121,31 @@ fn getting_films_from_api() { assert!(film_names.contains(&"Skuld")); }); } + +#[test] +fn getting_screenings_from_api() { + server_with_db(|server, db| { + let r = models::room::by_name("Main room", &db).unwrap(); + let f = models::film::by_title("Hellraiser", &db).unwrap(); + screening::create(&r, &f, + chrono::NaiveDate::from_ymd(2019, 10, 21), + chrono::NaiveTime::from_hms(18, 00, 00), + chrono::NaiveTime::from_hms(19, 34, 00), + &db).unwrap(); + + use ramaskrik::schema::screenings::dsl::*; + + let client = rocket::local::Client::new(server).unwrap(); + let mut response = client.get("/screenings").dispatch(); + assert_eq!(response.content_type(), Some(ContentType::JSON)); + + let fetched_screenings: Vec<(screening::Screening, Option, Option)> = + serde_json::from_str(&response.body_string().unwrap()).unwrap(); + + assert_eq!(fetched_screenings.len(), 1); + + let (scr, ff, rr) = &fetched_screenings[0]; + assert_eq!(ff.as_ref().unwrap().title, "Hellraiser"); + assert_eq!(rr.as_ref().unwrap().name, "Main room"); + }); +} -- cgit v1.2.3