From dd22bcde98a781491ff3f2cc06ec66120abd29ab Mon Sep 17 00:00:00 2001 From: Magnus Hoff Date: Mon, 23 Oct 2017 15:48:32 +0200 Subject: [PATCH] Add support for filtering _changes by article_id --- src/resources/changes_resource.rs | 68 +++++++++++++++++++------------ 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/src/resources/changes_resource.rs b/src/resources/changes_resource.rs index bed39e7..feb92bd 100644 --- a/src/resources/changes_resource.rs +++ b/src/resources/changes_resource.rs @@ -25,7 +25,6 @@ pub struct ChangesLookup { state: State, } -// TODO: Optionally filter by article_id // TODO: Optionally filter by author #[derive(Serialize, Deserialize, Default)] @@ -33,6 +32,8 @@ struct QueryParameters { after: Option, before: Option, + article_id: Option, + limit: Option, } @@ -45,6 +46,13 @@ impl QueryParameters { } } + fn article_id(self, article_id: Option) -> Self { + Self { + article_id, + ..self + } + } + fn limit(self, limit: i32) -> Self { Self { limit: if limit != DEFAULT_LIMIT { Some(limit) } else { None }, @@ -63,15 +71,19 @@ impl QueryParameters { } fn apply_query_config<'a>( - query: article_revisions::BoxedQuery<'a, diesel::sqlite::Sqlite>, + mut query: article_revisions::BoxedQuery<'a, diesel::sqlite::Sqlite>, + article_id: Option, limit: i32, ) -> article_revisions::BoxedQuery<'a, diesel::sqlite::Sqlite> { use diesel::prelude::*; - query - .limit(limit as i64 + 1) + if let Some(article_id) = article_id { + query = query.filter(article_revisions::article_id.eq(article_id)); + } + + query.limit(limit as i64 + 1) } impl ChangesLookup { @@ -96,17 +108,16 @@ impl ChangesLookup { _ => Err("`limit` argument must be in range [1, 100]"), }?; - Ok((pagination, limit)) + Ok((pagination, params.article_id, limit)) })()) - .and_then(move |(pagination, limit)| match pagination { + .and_then(move |(pagination, article_id, limit)| match pagination { Pagination::After(x) => Box::new( state.query_article_revision_stubs(move |query| { use diesel::prelude::*; - use schema::article_revisions::dsl::*; - apply_query_config(query, limit) - .filter(sequence_number.gt(x)) - .order(sequence_number.asc()) + apply_query_config(query, article_id, limit) + .filter(article_revisions::sequence_number.gt(x)) + .order(article_revisions::sequence_number.asc()) }).and_then(move |mut data| { let extra_element = if data.len() > limit as usize { data.pop() @@ -114,23 +125,29 @@ impl ChangesLookup { None }; + let args = + QueryParameters { + after: None, + before: None, + article_id, + limit: None, + } + .limit(limit); + Ok(Some(match extra_element { Some(x) => Box::new(TemporaryRedirectResource::new( - QueryParameters::default() - .limit(limit) + args .pagination(Pagination::Before(x.sequence_number)) .into_link() )) as BoxResource, None => Box::new(TemporaryRedirectResource::new( - QueryParameters::default() - .limit(limit) - .into_link() + args.into_link() )) as BoxResource, })) }) ) as Box, Error=::web::Error>>, - Pagination::Before(x) => Box::new(finished(Some(Box::new(ChangesResource::new(state, Some(x), limit)) as BoxResource))), - Pagination::None => Box::new(finished(Some(Box::new(ChangesResource::new(state, None, limit)) as BoxResource))), + Pagination::Before(x) => Box::new(finished(Some(Box::new(ChangesResource::new(state, Some(x), article_id, limit)) as BoxResource))), + Pagination::None => Box::new(finished(Some(Box::new(ChangesResource::new(state, None, article_id, limit)) as BoxResource))), }) ) } @@ -139,18 +156,20 @@ impl ChangesLookup { pub struct ChangesResource { state: State, before: Option, + article_id: Option, limit: i32, } impl ChangesResource { - pub fn new(state: State, before: Option, limit: i32) -> Self { - Self { state, before, limit } + pub fn new(state: State, before: Option, article_id: Option, limit: i32) -> Self { + Self { state, before, article_id, limit } } fn query_args(&self) -> QueryParameters { QueryParameters { after: None, before: self.before, + article_id: self.article_id, ..QueryParameters::default() } .limit(self.limit) @@ -198,17 +217,16 @@ impl Resource for ChangesResource { changes: &'a [Row], } - let before = self.before.clone(); - let limit = self.limit; + let (before, article_id, limit) = + (self.before.clone(), self.article_id.clone(), self.limit); let data = self.state.query_article_revision_stubs(move |query| { use diesel::prelude::*; - use schema::article_revisions::dsl::*; - let query = apply_query_config(query, limit) - .order(sequence_number.desc()); + let query = apply_query_config(query, article_id, limit) + .order(article_revisions::sequence_number.desc()); match before { - Some(x) => query.filter(sequence_number.lt(x)), + Some(x) => query.filter(article_revisions::sequence_number.lt(x)), None => query, } });