Refactor ChangesResource to handle pagination only in terms of before

This commit is contained in:
Magnus Hoff 2017-10-22 13:16:29 +02:00
parent 50b86db597
commit 7a63fdca0e

View file

@ -16,7 +16,7 @@ const PAGE_SIZE: i32 = 30;
pub struct ChangesResource { pub struct ChangesResource {
state: State, state: State,
pagination: Pagination<i32>, before: Option<i32>,
} }
impl ChangesResource { impl ChangesResource {
@ -40,15 +40,12 @@ impl ChangesResource {
Ok(Self { Ok(Self {
state, state,
pagination: match extra_element { before: extra_element.map(|x| x.sequence_number),
Some(x) => Pagination::Before(x.sequence_number),
None => Pagination::None
}
}) })
}) })
), ),
Pagination::Before(x) => Box::new(finished(Self { state, pagination })), Pagination::Before(x) => Box::new(finished(Self { state, before: Some(x) })),
Pagination::None => Box::new(finished(Self { state, pagination })), Pagination::None => Box::new(finished(Self { state, before: None })),
} }
} }
} }
@ -94,23 +91,18 @@ impl Resource for ChangesResource {
changes: &'a [Row], changes: &'a [Row],
} }
let pagination = self.pagination.clone(); let before = self.before.clone();
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::*; use schema::article_revisions::dsl::*;
let query = query let query = query
.order(sequence_number.desc())
.limit(PAGE_SIZE as i64 + 1); .limit(PAGE_SIZE as i64 + 1);
match pagination { match before {
Pagination::After(x) => query Some(x) => query.filter(sequence_number.lt(x)),
.filter(sequence_number.gt(x)) None => query,
.order(sequence_number.asc()),
Pagination::Before(x) => query
.filter(sequence_number.lt(x))
.order(sequence_number.desc()),
Pagination::None => query
.order(sequence_number.desc()),
} }
}); });
@ -120,27 +112,19 @@ impl Resource for ChangesResource {
.and_then(move |(mut data, head)| { .and_then(move |(mut data, head)| {
use std::iter::Iterator; use std::iter::Iterator;
if data.len() == 0 {
// TODO Handle degenerate case
unimplemented!("Cannot deal with empty result sets");
}
let extra_element = if data.len() > PAGE_SIZE as usize { let extra_element = if data.len() > PAGE_SIZE as usize {
data.pop() data.pop()
} else { } else {
None None
}; };
let (newer, older) = match self.pagination { let (newer, older) = match self.before {
Pagination::After(x) => { Some(x) => (
data.reverse();
(
extra_element.map(|_| NavLinks {
more: format!("?after={}", data.first().unwrap().sequence_number),
end: format!("_changes"),
}),
Some(NavLinks {
more: format!("?before={}", x + 1),
end: format!("?after=0"),
})
)
},
Pagination::Before(x) => (
Some(NavLinks { Some(NavLinks {
more: format!("?after={}", x - 1), more: format!("?after={}", x - 1),
end: format!("_changes"), end: format!("_changes"),
@ -150,7 +134,7 @@ impl Resource for ChangesResource {
end: format!("?after=0"), end: format!("?after=0"),
}) })
), ),
Pagination::None => ( None => (
None, None,
extra_element.map(|_| NavLinks { extra_element.map(|_| NavLinks {
more: format!("?before={}", data.last().unwrap().sequence_number), more: format!("?before={}", data.last().unwrap().sequence_number),