Add support for filtering _changes by article_id

This commit is contained in:
Magnus Hoff 2017-10-23 15:48:32 +02:00
parent 955254335d
commit dd22bcde98

View file

@ -25,7 +25,6 @@ pub struct ChangesLookup {
state: State, state: State,
} }
// TODO: Optionally filter by article_id
// TODO: Optionally filter by author // TODO: Optionally filter by author
#[derive(Serialize, Deserialize, Default)] #[derive(Serialize, Deserialize, Default)]
@ -33,6 +32,8 @@ struct QueryParameters {
after: Option<i32>, after: Option<i32>,
before: Option<i32>, before: Option<i32>,
article_id: Option<i32>,
limit: Option<i32>, limit: Option<i32>,
} }
@ -45,6 +46,13 @@ impl QueryParameters {
} }
} }
fn article_id(self, article_id: Option<i32>) -> Self {
Self {
article_id,
..self
}
}
fn limit(self, limit: i32) -> Self { fn limit(self, limit: i32) -> Self {
Self { Self {
limit: if limit != DEFAULT_LIMIT { Some(limit) } else { None }, limit: if limit != DEFAULT_LIMIT { Some(limit) } else { None },
@ -63,15 +71,19 @@ impl QueryParameters {
} }
fn apply_query_config<'a>( 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<i32>,
limit: i32, limit: i32,
) )
-> article_revisions::BoxedQuery<'a, diesel::sqlite::Sqlite> -> article_revisions::BoxedQuery<'a, diesel::sqlite::Sqlite>
{ {
use diesel::prelude::*; use diesel::prelude::*;
query if let Some(article_id) = article_id {
.limit(limit as i64 + 1) query = query.filter(article_revisions::article_id.eq(article_id));
}
query.limit(limit as i64 + 1)
} }
impl ChangesLookup { impl ChangesLookup {
@ -96,17 +108,16 @@ impl ChangesLookup {
_ => Err("`limit` argument must be in range [1, 100]"), _ => 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( Pagination::After(x) => Box::new(
state.query_article_revision_stubs(move |query| { state.query_article_revision_stubs(move |query| {
use diesel::prelude::*; use diesel::prelude::*;
use schema::article_revisions::dsl::*;
apply_query_config(query, limit) apply_query_config(query, article_id, limit)
.filter(sequence_number.gt(x)) .filter(article_revisions::sequence_number.gt(x))
.order(sequence_number.asc()) .order(article_revisions::sequence_number.asc())
}).and_then(move |mut data| { }).and_then(move |mut data| {
let extra_element = if data.len() > limit as usize { let extra_element = if data.len() > limit as usize {
data.pop() data.pop()
@ -114,23 +125,29 @@ impl ChangesLookup {
None None
}; };
let args =
QueryParameters {
after: None,
before: None,
article_id,
limit: None,
}
.limit(limit);
Ok(Some(match extra_element { Ok(Some(match extra_element {
Some(x) => Box::new(TemporaryRedirectResource::new( Some(x) => Box::new(TemporaryRedirectResource::new(
QueryParameters::default() args
.limit(limit)
.pagination(Pagination::Before(x.sequence_number)) .pagination(Pagination::Before(x.sequence_number))
.into_link() .into_link()
)) as BoxResource, )) as BoxResource,
None => Box::new(TemporaryRedirectResource::new( None => Box::new(TemporaryRedirectResource::new(
QueryParameters::default() args.into_link()
.limit(limit)
.into_link()
)) as BoxResource, )) as BoxResource,
})) }))
}) })
) as Box<Future<Item=Option<BoxResource>, Error=::web::Error>>, ) as Box<Future<Item=Option<BoxResource>, Error=::web::Error>>,
Pagination::Before(x) => Box::new(finished(Some(Box::new(ChangesResource::new(state, Some(x), 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, 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 { pub struct ChangesResource {
state: State, state: State,
before: Option<i32>, before: Option<i32>,
article_id: Option<i32>,
limit: i32, limit: i32,
} }
impl ChangesResource { impl ChangesResource {
pub fn new(state: State, before: Option<i32>, limit: i32) -> Self { pub fn new(state: State, before: Option<i32>, article_id: Option<i32>, limit: i32) -> Self {
Self { state, before, limit } Self { state, before, article_id, limit }
} }
fn query_args(&self) -> QueryParameters { fn query_args(&self) -> QueryParameters {
QueryParameters { QueryParameters {
after: None, after: None,
before: self.before, before: self.before,
article_id: self.article_id,
..QueryParameters::default() ..QueryParameters::default()
} }
.limit(self.limit) .limit(self.limit)
@ -198,17 +217,16 @@ impl Resource for ChangesResource {
changes: &'a [Row], changes: &'a [Row],
} }
let before = self.before.clone(); let (before, article_id, limit) =
let limit = self.limit; (self.before.clone(), self.article_id.clone(), self.limit);
let data = self.state.query_article_revision_stubs(move |query| { let data = self.state.query_article_revision_stubs(move |query| {
use diesel::prelude::*; use diesel::prelude::*;
use schema::article_revisions::dsl::*;
let query = apply_query_config(query, limit) let query = apply_query_config(query, article_id, limit)
.order(sequence_number.desc()); .order(article_revisions::sequence_number.desc());
match before { match before {
Some(x) => query.filter(sequence_number.lt(x)), Some(x) => query.filter(article_revisions::sequence_number.lt(x)),
None => query, None => query,
} }
}); });