Skip to content
Snippets Groups Projects
Verified Commit cd590ffc authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Cleanup data retrieval

parent 09643888
No related branches found
No related tags found
No related merge requests found
use diesel::*;
use crate::dto::*;
use crate::models::*;
use crate::schema::*;
pub fn load_title(db: &PgConnection, title: Title) -> QueryResult<TitleDto> {
let title_names: Vec<TitleName> = TitleName::belonging_to(&title)
.load::<TitleName>(db)?;
let title_descriptions: Vec<TitleDescription> = TitleDescription::belonging_to(&title)
.load::<TitleDescription>(db)?;
let title_cast: Vec<(TitleCast, Person)> = TitleCast::belonging_to(&title)
.inner_join(people::table)
.load::<(TitleCast, Person)>(db)?;
let title_genres: Vec<(TitleGenre, Genre)> = TitleGenre::belonging_to(&title)
.inner_join(genres::table)
.load::<(TitleGenre, Genre)>(db)?;
let title_ratings: Vec<TitleRating> = TitleRating::belonging_to(&title)
.load::<TitleRating>(db)?;
let title_images: Vec<TitleImage> = TitleImage::belonging_to(&title)
.load::<TitleImage>(db)?;
let title_media: Vec<TitleMedium> = TitleMedium::belonging_to(&title)
.load::<TitleMedium>(db)?;
let title_subtitles: Vec<TitleSubtitle> = TitleSubtitle::belonging_to(&title)
.load::<TitleSubtitle>(db)?;
Ok(process_title(
title, title_names, title_descriptions,
title_cast, title_genres, title_ratings,
title_images, title_media, title_subtitles,
))
}
pub fn load_titles(db: &PgConnection, titles: Vec<Title>) -> QueryResult<Vec<TitleDto>> {
let title_names: Vec<Vec<TitleName>> = TitleName::belonging_to(&titles)
.load::<TitleName>(db)?
.grouped_by(&titles);
let title_descriptions: Vec<Vec<TitleDescription>> = TitleDescription::belonging_to(&titles)
.load::<TitleDescription>(db)?
.grouped_by(&titles);
let title_cast: Vec<Vec<(TitleCast, Person)>> = TitleCast::belonging_to(&titles)
.inner_join(people::table)
.load::<(TitleCast, Person)>(db)?
.grouped_by(&titles);
let title_genres: Vec<Vec<(TitleGenre, Genre)>> = TitleGenre::belonging_to(&titles)
.inner_join(genres::table)
.load::<(TitleGenre, Genre)>(db)?
.grouped_by(&titles);
let title_ratings: Vec<Vec<TitleRating>> = TitleRating::belonging_to(&titles)
.load::<TitleRating>(db)?
.grouped_by(&titles);
let title_images: Vec<Vec<TitleImage>> = TitleImage::belonging_to(&titles)
.load::<TitleImage>(db)?
.grouped_by(&titles);
let title_media: Vec<Vec<TitleMedium>> = TitleMedium::belonging_to(&titles)
.load::<TitleMedium>(db)?
.grouped_by(&titles);
let title_subtitles: Vec<Vec<TitleSubtitle>> = TitleSubtitle::belonging_to(&titles)
.load::<TitleSubtitle>(db)?
.grouped_by(&titles);
Ok(titles.into_iter()
.zip(title_names)
.zip(title_descriptions)
.zip(title_cast)
.zip(title_genres)
.zip(title_ratings)
.zip(title_images)
.zip(title_media)
.zip(title_subtitles)
.map(|tuple| {
let ((((((((title, akas), descriptions),
cast), genres), ratings),
images), media), subtitles) = tuple;
process_title(title, akas, descriptions, cast, genres, ratings, images, media, subtitles)
}).collect::<Vec<TitleDto>>())
}
fn process_title(
title: Title, names: Vec<TitleName>, descriptions: Vec<TitleDescription>,
cast: Vec<(TitleCast, Person)>, genres: Vec<(TitleGenre, Genre)>, ratings: Vec<TitleRating>,
images: Vec<TitleImage>, media: Vec<TitleMedium>, subtitles: Vec<TitleSubtitle>
) -> TitleDto {
TitleDto::of(
title,
names.into_iter().map(|src| {
TitleNameDto::from(src)
}).collect::<Vec<_>>(),
descriptions.into_iter().map(|src| {
TitleDescriptionDto::from(src)
}).collect::<Vec<_>>(),
cast.into_iter().map(|src| {
let (cast, person) = src;
TitleCastDto::of(cast, person)
}).collect::<Vec<_>>(),
genres.into_iter().map(|(_, src)| {
GenreDto::from(src)
}).collect::<Vec<_>>(),
ratings.into_iter().map(|src| {
TitleRatingDto::from(src)
}).collect::<Vec<_>>(),
images.into_iter().map(|src| {
TitleImageDto::from(src)
}).collect::<Vec<_>>(),
media.into_iter().map(|src| {
TitleMediaDto::from(src)
}).collect::<Vec<_>>(),
subtitles.into_iter().map(|src| {
TitleSubtitleDto::from(src)
}).collect::<Vec<_>>(),
)
}
\ No newline at end of file
...@@ -5,3 +5,5 @@ extern crate dotenv; ...@@ -5,3 +5,5 @@ extern crate dotenv;
pub mod schema; pub mod schema;
pub mod models; pub mod models;
pub mod dto; pub mod dto;
pub mod dto_helpers;
pub mod param_helpers;
\ No newline at end of file
...@@ -8,19 +8,17 @@ extern crate rocket_contrib; ...@@ -8,19 +8,17 @@ extern crate rocket_contrib;
use diesel::prelude::*; use diesel::prelude::*;
use dotenv::dotenv; use dotenv::dotenv;
use rocket::http::RawStr;
use rocket::request::FromParam;
use rocket_contrib::databases::diesel; use rocket_contrib::databases::diesel;
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
use uuid::Uuid;
use media_backend::dto::{GenreDto, GenreWithTitlesDto, TitleCastDto, TitleDescriptionDto, TitleDto, TitleImageDto, TitleMediaDto, TitleNameDto, TitleRatingDto, TitleSubtitleDto}; use media_backend::dto::*;
use media_backend::dto_helpers::{load_title, load_titles};
use media_backend::models::*; use media_backend::models::*;
use media_backend::param_helpers::ParamUuid;
#[database("mediaflix")] #[database("mediaflix")]
struct MediaflixConnection(diesel::PgConnection); struct MediaflixConnection(diesel::PgConnection);
#[get("/api/v1/genres")] #[get("/api/v1/genres")]
fn list_genres(db: MediaflixConnection) -> QueryResult<Json<Vec<Genre>>> { fn list_genres(db: MediaflixConnection) -> QueryResult<Json<Vec<Genre>>> {
use media_backend::schema::*; use media_backend::schema::*;
...@@ -28,109 +26,41 @@ fn list_genres(db: MediaflixConnection) -> QueryResult<Json<Vec<Genre>>> { ...@@ -28,109 +26,41 @@ fn list_genres(db: MediaflixConnection) -> QueryResult<Json<Vec<Genre>>> {
Ok(Json(query.load::<Genre>(&db.0)?)) Ok(Json(query.load::<Genre>(&db.0)?))
} }
struct ParamUuid(uuid::Uuid);
impl FromParam<'_> for ParamUuid {
type Error = uuid::parser::ParseError;
fn from_param(param: &RawStr) -> Result<Self, Self::Error> {
return Ok(ParamUuid(Uuid::parse_str(param.as_str())?));
}
}
#[get("/api/v1/genres/<id>")] #[get("/api/v1/genres/<id>")]
fn get_genre(db: MediaflixConnection, id: ParamUuid) -> QueryResult<Json<GenreWithTitlesDto>> { fn get_genre(db: MediaflixConnection, id: ParamUuid) -> QueryResult<Json<GenreWithTitlesDto>> {
use media_backend::schema::*; use media_backend::schema::*;
let genre: Genre = genres::table let genre: Genre = genres::table
.find(id.0) .find(id.uuid())
.first::<Genre>(&db.0)?; .first::<Genre>(&db.0)?;
let titles: Vec<Title> = title_genres::table let titles: Vec<Title> = title_genres::table
.filter(title_genres::genre_id.eq(genre.id)) .filter(title_genres::genre_id.eq(genre.id))
.inner_join(titles::table) .inner_join(titles::table)
.select(titles::all_columns) .select(titles::all_columns)
.load::<Title>(&db.0)?; .load::<Title>(&db.0)?;
let title_names: Vec<Vec<TitleName>> = TitleName::belonging_to(&titles)
.load::<TitleName>(&db.0)?
.grouped_by(&titles);
let title_descriptions: Vec<Vec<TitleDescription>> = TitleDescription::belonging_to(&titles)
.load::<TitleDescription>(&db.0)?
.grouped_by(&titles);
let title_cast: Vec<Vec<(TitleCast, Person)>> = TitleCast::belonging_to(&titles)
.inner_join(people::table)
.load::<(TitleCast, Person)>(&db.0)?
.grouped_by(&titles);
let title_genres: Vec<Vec<(TitleGenre, Genre)>> = TitleGenre::belonging_to(&titles)
.inner_join(genres::table)
.load::<(TitleGenre, Genre)>(&db.0)?
.grouped_by(&titles);
let title_ratings: Vec<Vec<TitleRating>> = TitleRating::belonging_to(&titles)
.load::<TitleRating>(&db.0)?
.grouped_by(&titles);
let title_images: Vec<Vec<TitleImage>> = TitleImage::belonging_to(&titles)
.load::<TitleImage>(&db.0)?
.grouped_by(&titles);
let title_media: Vec<Vec<TitleMedium>> = TitleMedium::belonging_to(&titles)
.load::<TitleMedium>(&db.0)?
.grouped_by(&titles);
let title_subtitles: Vec<Vec<TitleSubtitle>> = TitleSubtitle::belonging_to(&titles)
.load::<TitleSubtitle>(&db.0)?
.grouped_by(&titles);
Ok(Json(GenreWithTitlesDto { Ok(Json(GenreWithTitlesDto {
genre: GenreDto::from(genre), genre: GenreDto::from(genre),
titles: titles.into_iter() titles: load_titles(&db.0, titles)?,
.zip(title_names)
.zip(title_descriptions)
.zip(title_cast)
.zip(title_genres)
.zip(title_ratings)
.zip(title_images)
.zip(title_media)
.zip(title_subtitles)
.map(|tuple| {
let ((((((((title, akas), descriptions),
cast), genres), ratings),
images), media), subtitles) = tuple;
TitleDto::of(
title,
akas.into_iter().map(|src| {
TitleNameDto::from(src)
}).collect::<Vec<_>>(),
descriptions.into_iter().map(|src| {
TitleDescriptionDto::from(src)
}).collect::<Vec<_>>(),
cast.into_iter().map(|src| {
let (cast, person) = src;
TitleCastDto::of(cast, person)
}).collect::<Vec<_>>(),
genres.into_iter().map(|(_, src)| {
GenreDto::from(src)
}).collect::<Vec<_>>(),
ratings.into_iter().map(|src| {
TitleRatingDto::from(src)
}).collect::<Vec<_>>(),
images.into_iter().map(|src| {
TitleImageDto::from(src)
}).collect::<Vec<_>>(),
media.into_iter().map(|src| {
TitleMediaDto::from(src)
}).collect::<Vec<_>>(),
subtitles.into_iter().map(|src| {
TitleSubtitleDto::from(src)
}).collect::<Vec<_>>(),
)
}).collect::<Vec<TitleDto>>(),
})) }))
} }
#[get("/api/v1/titles")]
fn list_titles(db: MediaflixConnection) -> QueryResult<Json<Vec<TitleDto>>> {
use media_backend::schema::*;
let titles = titles::table
.load::<Title>(&db.0)?;
Ok(Json(load_titles(&db.0, titles)?))
}
#[get("/api/v1/titles/<title>")] #[get("/api/v1/titles/<title>")]
fn get_title(db: MediaflixConnection, title: ParamUuid) -> QueryResult<Json<Title>> { fn get_title(db: MediaflixConnection, title: ParamUuid) -> QueryResult<Json<TitleDto>> {
use media_backend::schema::*; use media_backend::schema::*;
let query = titles::table let title = load_title(
.find(title.0) &db.0,
.into_boxed(); titles::table
Ok(Json(query.first::<Title>(&db.0)?)) .find(title.uuid())
.first::<Title>(&db.0)?,
)?;
Ok(Json(title))
} }
fn main() { fn main() {
...@@ -143,6 +73,7 @@ fn main() { ...@@ -143,6 +73,7 @@ fn main() {
rocket::routes![ rocket::routes![
list_genres, list_genres,
get_genre, get_genre,
list_titles,
get_title get_title
], ],
) )
......
use rocket::request::FromParam;
use rocket::http::RawStr;
use uuid::Uuid;
pub struct ParamUuid(uuid::Uuid);
impl ParamUuid {
pub fn uuid(&self) -> uuid::Uuid {
self.0
}
}
impl FromParam<'_> for ParamUuid {
type Error = uuid::parser::ParseError;
fn from_param(param: &RawStr) -> Result<Self, Self::Error> {
return Ok(ParamUuid(Uuid::parse_str(param.as_str())?));
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment