Skip to content

Commit

Permalink
feat: refactor constructors queries using the builder architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
thibault-cne committed Jan 31, 2024
1 parent 14ef7d7 commit 1c8c923
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 110 deletions.
88 changes: 14 additions & 74 deletions api/src/constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,13 @@ use shared::prelude::*;

use crate::error::Result;

#[get(
"/<series>/constructors?<limit>&<page>&<driver_number>&<driver_ref>&<constructor>&<circuit>&<grid>&<result>",
)]
#[get("/<series>/constructors?<param..>")]
pub fn constructors(
db: &State<ConnectionPool>,
series: Series,
limit: Option<Limit>,
page: Option<Page>,
driver_number: Option<DriverNumber>,
driver_ref: Option<DriverRef>,
constructor: Option<ConstructorName>,
circuit: Option<Circuit>,
grid: Option<Grid>,
result: Option<RaceResult>,
param: ConstructorParameter,
) -> Result<Json<ConstructorResponse>> {
let filter = ConstructorFilter {
limit,
page,
driver_ref,
driver_number,
constructor,
circuit,
grid,
result,
year: None,
round: None,
};

let (constructors, pagination) = constructors_inner_handler(db, series, filter)?;
let (constructors, pagination) = constructors_inner_handler(db, series, param.into())?;

let response = ConstructorResponse {
pagination,
Expand All @@ -47,34 +25,15 @@ pub fn constructors(
Ok(Json(response))
}

#[get(
"/<series>/<year>/constructor?<limit>&<page>&<driver_number>&<driver_ref>&<constructor>&<circuit>&<grid>&<result>",
)]
#[get("/<series>/<year>/constructors?<param..>")]
pub fn constructors_by_year(
db: &State<ConnectionPool>,
series: Series,
year: Year,
limit: Option<Limit>,
page: Option<Page>,
driver_number: Option<DriverNumber>,
driver_ref: Option<DriverRef>,
constructor: Option<ConstructorName>,
circuit: Option<Circuit>,
grid: Option<Grid>,
result: Option<RaceResult>,
param: ConstructorParameter,
) -> Result<Json<ConstructorResponse>> {
let filter = ConstructorFilter {
limit,
page,
driver_ref,
driver_number,
constructor,
circuit,
grid,
result,
year: Some(year),
round: None,
};
let mut filter: ConstructorFilter = param.into();
filter.year = Some(year);

let (constructors, pagination) = constructors_inner_handler(db, series, filter)?;

Expand All @@ -87,35 +46,17 @@ pub fn constructors_by_year(
Ok(Json(response))
}

#[get(
"/<series>/<year>/<round>/constructors?<limit>&<page>&<driver_number>&<driver_ref>&<constructor>&<circuit>&<grid>&<result>",
)]
#[get("/<series>/<year>/<round>/constructors?<param..>")]
pub fn constructors_by_year_and_round(
db: &State<ConnectionPool>,
series: Series,
year: Year,
round: Round,
limit: Option<Limit>,
page: Option<Page>,
driver_number: Option<DriverNumber>,
driver_ref: Option<DriverRef>,
constructor: Option<ConstructorName>,
circuit: Option<Circuit>,
grid: Option<Grid>,
result: Option<RaceResult>,
param: ConstructorParameter,
) -> Result<Json<ConstructorResponse>> {
let filter = ConstructorFilter {
limit,
page,
driver_ref,
driver_number,
constructor,
circuit,
grid,
result,
year: Some(year),
round: Some(round),
};
let mut filter: ConstructorFilter = param.into();
filter.year = Some(year);
filter.round = Some(round);

let (constructors, pagination) = constructors_inner_handler(db, series, filter)?;

Expand All @@ -134,9 +75,8 @@ fn constructors_inner_handler(
filter: ConstructorFilter,
) -> Result<(Vec<Constructor>, Pagination)> {
let pool = &mut db.from_series(series).get()?;
let res = pool.transaction(|conn| {
application::models::Constructor::filter(filter).load_and_count_pages(conn)
});
let res =
pool.transaction(|conn| application::builders::ConstructorBuilder::new(filter).load(conn));

Ok(res.map(|(constructors, pagination)| {
(
Expand Down
94 changes: 59 additions & 35 deletions application/src/constructors.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,26 @@
use diesel::{
helper_types::{AsSelect, Eq, InnerJoin, InnerJoinOn, InnerJoinQuerySource, IntoBoxed, Select},
prelude::*,
sql_types::{Bool, Nullable},
};
use diesel::prelude::*;

use shared::filters::ConstructorFilter;
use shared::models::Pagination;
use types::*;

use crate::models::Constructor;
use crate::prelude::*;

type BoxedConditionSource = InnerJoinQuerySource<
InnerJoinQuerySource<
InnerJoinQuerySource<
InnerJoinQuerySource<results::table, drivers::table>,
constructors::table,
>,
races::table,
>,
circuits::table,
Eq<circuits::circuit_id, races::circuit_id>,
>;
type BoxedCondition =
Box<dyn BoxableExpression<BoxedConditionSource, super::Backend, SqlType = Nullable<Bool>>>;

type BoxedQuerySource = InnerJoinOn<
InnerJoin<
InnerJoin<InnerJoin<results::table, drivers::table>, constructors::table>,
races::table,
>,
circuits::table,
Eq<circuits::circuit_id, races::circuit_id>,
>;
type BoxedQuery = IntoBoxed<
'static,
Select<BoxedQuerySource, AsSelect<Constructor, super::Backend>>,
super::Backend,
>;

impl Constructor {
pub struct ConstructorBuilder(ConstructorFilter);

impl ConstructorBuilder {
pub fn new(filter: ConstructorFilter) -> Self {
Self(filter)
}

pub fn load(
self,
conn: &mut MysqlConnection,
) -> Result<(Vec<Constructor>, Pagination), diesel::result::Error> {
Self::filter(self.0).load_and_count_pages(conn)
}

fn boxed() -> BoxedQuery {
results::table
.inner_join(drivers::table)
Expand All @@ -50,7 +33,7 @@ impl Constructor {
.into_boxed()
}

pub fn filter(filter: ConstructorFilter) -> Paginated<BoxedQuery> {
fn filter(filter: ConstructorFilter) -> Paginated<BoxedQuery> {
let limit = filter.limit.unwrap_or_default().0 as i64;
let page = filter.page.unwrap_or_default().0 as i64;

Expand Down Expand Up @@ -102,3 +85,44 @@ impl Condition {
})
}
}

mod types {
use diesel::{
helper_types::{
AsSelect, Eq, InnerJoin, InnerJoinOn, InnerJoinQuerySource, IntoBoxed, Select,
},
prelude::*,
sql_types::{Bool, Nullable},
};

use crate::models::Constructor;
use crate::prelude::*;

pub type BoxedConditionSource = InnerJoinQuerySource<
InnerJoinQuerySource<
InnerJoinQuerySource<
InnerJoinQuerySource<results::table, drivers::table>,
constructors::table,
>,
races::table,
>,
circuits::table,
Eq<circuits::circuit_id, races::circuit_id>,
>;
pub type BoxedCondition =
Box<dyn BoxableExpression<BoxedConditionSource, crate::Backend, SqlType = Nullable<Bool>>>;

pub type BoxedQuerySource = InnerJoinOn<
InnerJoin<
InnerJoin<InnerJoin<results::table, drivers::table>, constructors::table>,
races::table,
>,
circuits::table,
Eq<circuits::circuit_id, races::circuit_id>,
>;
pub type BoxedQuery = IntoBoxed<
'static,
Select<BoxedQuerySource, AsSelect<Constructor, crate::Backend>>,
crate::Backend,
>;
}
1 change: 1 addition & 0 deletions application/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod prelude {
}

pub mod builders {
pub use super::constructors::ConstructorBuilder;
pub use super::driver_standing::DriverStandingBuilder;
pub use super::drivers::DriverBuilder;
}
Expand Down
2 changes: 1 addition & 1 deletion shared/src/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct DriverFilter {
pub round: Option<Round>,
}

#[derive(Debug, Clone)]
#[derive(Debug, Default)]
pub struct ConstructorFilter {
pub limit: Option<Limit>,
pub page: Option<Page>,
Expand Down
12 changes: 12 additions & 0 deletions shared/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ struct_parameters!(
limit: Limit,
page: Page
} => crate::filters::DriverFilter;

ConstructorParameter {
driver_ref: DriverRef,
driver_number: DriverNumber,
constructor: ConstructorName,
circuit: Circuit,
grid: Grid,
result: RaceResult,
limit: Limit,
page: Page
} => crate::filters::ConstructorFilter;

DriverStandingParameter {
name: DriverRef,
result: RaceResult,
Expand Down

0 comments on commit 1c8c923

Please sign in to comment.