Refactor handling of pagination query arguments

This commit is contained in:
Magnus Hoff 2017-10-17 11:35:21 +02:00
parent a42010a1f8
commit 0dacad5a3e
5 changed files with 43 additions and 15 deletions

View file

@ -16,6 +16,7 @@ extern crate percent_encoding;
extern crate pulldown_cmark; extern crate pulldown_cmark;
extern crate r2d2; extern crate r2d2;
extern crate r2d2_diesel; extern crate r2d2_diesel;
extern crate serde;
extern crate serde_json; extern crate serde_json;
extern crate serde_urlencoded; extern crate serde_urlencoded;
extern crate slug; extern crate slug;

View file

@ -9,14 +9,16 @@ use site::Layout;
use state::State; use state::State;
use web::{Resource, ResponseFuture}; use web::{Resource, ResponseFuture};
use super::pagination::Pagination;
pub struct ChangesResource { pub struct ChangesResource {
state: State, state: State,
before: Option<i32>, before: Option<i32>,
} }
impl ChangesResource { impl ChangesResource {
pub fn new(state: State, before: Option<i32>) -> Self { pub fn new(state: State, pagination: Pagination<i32>) -> Self {
Self { state, before } Self { state, before: match pagination { Pagination::Before(x) => Some(x), _ => None } }
} }
} }

View file

@ -1,3 +1,5 @@
pub mod pagination;
mod article_redirect_resource; mod article_redirect_resource;
mod article_resource; mod article_resource;
mod changes_resource; mod changes_resource;

View file

@ -0,0 +1,29 @@
use serde;
use serde_urlencoded;
#[derive(Deserialize)]
struct PaginationStruct<T> {
after: Option<T>,
before: Option<T>,
}
pub enum Pagination<T> {
After(T),
Before(T),
None,
}
impl<T> PaginationStruct<T> {
fn into_enum(self) -> Pagination<T> {
match (self.after, self.before) {
(Some(x), _) => Pagination::After(x),
(None, Some(x)) => Pagination::Before(x),
_ => Pagination::None,
}
}
}
pub fn from_str<'a, T: serde::Deserialize<'a>>(s: &'a str) -> Result<Pagination<T>, serde::de::value::Error> {
let pagination: PaginationStruct<T> = serde_urlencoded::from_str(s)?;
Ok(pagination.into_enum())
}

View file

@ -2,10 +2,9 @@ use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::str::Utf8Error; use std::str::Utf8Error;
use futures::{Future, finished, failed}; use futures::{Future, finished, failed, done};
use futures::future::FutureResult; use futures::future::FutureResult;
use percent_encoding::percent_decode; use percent_encoding::percent_decode;
use serde_urlencoded;
use slug::slugify; use slug::slugify;
use resources::*; use resources::*;
@ -84,17 +83,12 @@ impl WikiLookup {
("_assets", Some(asset)) => ("_assets", Some(asset)) =>
Box::new(asset_lookup(asset)), Box::new(asset_lookup(asset)),
("_changes", None) => { ("_changes", None) => {
#[derive(Deserialize)] Box::new(done(
struct Query { pagination::from_str(query.unwrap_or("")).map_err(Into::into)
before: Option<i32>, .and_then(|pagination| Ok(Some(
} Box::new(ChangesResource::new(self.state.clone(), pagination)) as BoxResource
)))
let query: Query = match serde_urlencoded::from_str(query.unwrap_or("")) { ))
Ok(x) => x,
Err(x) => return Box::new(failed(x.into())),
};
Box::new(finished(Some(Box::new(ChangesResource::new(self.state.clone(), query.before)) as BoxResource)))
}, },
("_new", None) => ("_new", None) =>
Box::new(finished(Some(Box::new(NewArticleResource::new(self.state.clone(), None)) as BoxResource))), Box::new(finished(Some(Box::new(NewArticleResource::new(self.state.clone(), None)) as BoxResource))),